Dans mon microservice REST, je demande un objet à un autre service qui me renvoie un énorme JSON imbriqué, par exemple:
public class FullAddress { String address; RawValue contactInfo; }
Ce dont j'ai besoin pour récupérer ces données à partir d'un autre service, effectuer une modification uniquement dans le premier champ, puis les envoyer via HTTP. Ce que j'essaie d'éviter, c'est de désérialiser tout de mon côté et d'avoir à maintenir les classes ici. Existe-t-il un moyen d'obtenir la valeur brute de contact_info
et d'avoir juste la représentation de l'adresse avec Jackson? Quelque chose comme ça:
{ "address": "19th Street", "contact_info": { "phones": { "home": { "first": { "another_nested": 1234 } } } } }
5 Réponses :
Vous pouvez utiliser JsonIgnoreProperties
sur les documents de classe afin qu'il ignore toutes les autres propriétés qui ne sont pas présentes dans la classe
// To ignore any unknown properties in JSON input without exception: @JsonIgnoreProperties(ignoreUnknown=true)
Je pense que l'utilisateur souhaite désérialiser les données, les modifier et les remettre en série dans json. Avec @JsonIgnoreProperties
vous perdez des données qui ont été ignorées.
Je pense que vous avez manqué le point de la question. J'ai fourni quelques solutions ma réponse .
L'approche la plus simple consisterait à utiliser JsonNode
:
@Data public class FullAddress { private String address; @JsonDeserialize(using = RawJsonDeserializer.class) private String contactInfo; }
Ou soit Map<String, Object>
:
public class RawJsonDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { ObjectMapper mapper = (ObjectMapper) jp.getCodec(); JsonNode node = mapper.readTree(jp); return mapper.writeValueAsString(node); } }
Cela fonctionne à la fois pour la sérialisation et la désérialisation.
Cependant, si vous souhaitez stocker le JSON brut, vous pouvez définir un désérialiseur personnalisé:
@Data public class FullAddress { private String address; private Map<String, Object> contactInfo; }
Et puis utilisez-le comme suit:
@Data public class FullAddress { private String address; private JsonNode contactInfo; }
Pour sérialisation retour, cependant, vous pouvez annoter le contactInfo
champ avec @JsonRawValue
.
Fonctionne comme un charme!
cela ne fonctionne pas lors de l'utilisation de xml, car Jackson conservera une représentation JSON interne du XML.
Il existe également ObjectMapper.readerForUpdating
qui vous permet essentiellement de mettre à jour sur place un objet JSON. Cependant, il n'y a pas beaucoup de documentation à ce sujet:
Exemple ici: https://www.logicbig.com/tutorials/misc/jackson/reader-for-updating.html
(Toutes mes excuses pour une réponse partielle ici - mais cela pourrait être utile pour quelqu'un)
Je recommande de toujours définir des classes de modèle pour votre chaîne JSON, même si vous ne devez mapper que quelques champs de cette chaîne JSON. C'est plus soigné et à l'avenir, n'importe qui peut facilement ajouter des champs supplémentaires au modèle si cela est nécessaire. Jackson prend en charge le mappage partiel.
Exemple de travail complet à Kotlin:
import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.ObjectMapper import org.junit.Test class Test { data class ModelInner( var attributeB1: String? = null, ) data class ModelRoot( var attributeA2: List<ModelInner>? = null, ) @Test fun test0() { val json = """ { "attributeA0": "A0", "attributeA1": "A1", "attributeA2": [ { "attributeB0": "B00", "attributeB1": "B01" }, { "attributeB0": "B10", "attributeB1": "B11" } ] } """ val om = ObjectMapper() om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) val order = om.readValue(json, ModelRoot::class.java) print(order) } }
Production:
ModelRoot (attributA2 = [ModelInner (attributB1 = B01), ModelInner (attributB1 = B11)])
Une autre solution consiste à utiliser @JsonAnyGetter
@JsonAnySetter
. Voir la rédaction ici: https://www.concretepage.com/jackson-api/jackson-jsonanygetter-and-jsonanysetter-example
vérifiez ce newtonsoft.com/json/help/html/SerializingJSONFragments.htm
J'apprécie tout commentaire sur ma réponse .