Convertir JsonNode en POJO


143

Cela peut sembler un peu inhabituel, mais je recherche un moyen efficace de transformer / mapper un JsonNodeen un fichier POJO.

Je stocke certaines des informations de mon modèle dans des fichiers json et je dois prendre en charge quelques versions de mon modèle.

Ce que je fais, c'est charger le fichier json en mémoire dans un JsonNode, appliquer quelques stratégies de contrôle de version pour le faire correspondre à la dernière version de mon modèle.

    ObjectMapper mapper = new ObjectMapper();
    BufferedReader fileReader = new BufferedReader(new FileReader(projPath));

    JsonNode rootNode = mapper.readTree(fileReader);

    //Upgrade our file in memory
    applyVersioningStrategy(rootNode);

    ProjectModel project = mapJsonNodeToProject(rootNode);

À moins qu'il n'y ait un moyen plus rapide de le faire, je finirai probablement par appliquer simplement manuellement le JsonNodesà mon modèle

Réponses:


264

Dans Jackson 2.4, vous pouvez convertir comme suit:

MyClass newJsonNode = jsonObjectMapper.treeToValue(someJsonNode, MyClass.class);

jsonObjectMapperest un Jackson ObjectMapper.


Dans les anciennes versions de Jackson, ce serait

MyClass newJsonNode = jsonObjectMapper.readValue(someJsonNode, MyClass.class);

19
Malheureusement, il n'y a pas de variante treeToValue (TreeNode n, TypeReference <T> type) comme c'est le cas pour readValue (). Mauvaise nouvelle pour quiconque traite avec des types plus complexes de génériques :(
Espinosa

13
@Espinosa Per jackson-databind # 1294 , vous voudrez quelque chose comme (malheureusement plus verbeux)jsonObjectMapper.readValue(jsonObjectMapper.treeAsTokens(someJsonNode), someTypeReference)
M. Justin

Pour les anciennes versions, utilisez:objectMapper.treeToValue(jsonNode, MyClass.class)
amod

2
Vous pouvez également utiliser cette méthode dans StdDeserializer: p.codec.treeToValue.
galcyurio

@icedtrees jsonObjectMapper est une instance de JsonObjectMapper ou juste l'ObjectMapper
KNDheeraj

8

Cela devrait faire l'affaire:

mapper.readValue(fileReader, MyClass.class);

Je dis que je devrais parce que je l'utilise avec un String, pas un, BufferedReadermais cela devrait toujours fonctionner.

Voici mon code:

String inputString = // I grab my string here
MySessionClass sessionObject;
try {
    ObjectMapper objectMapper = new ObjectMapper();
    sessionObject = objectMapper.readValue(inputString, MySessionClass.class);

Voici la documentation officielle pour cet appel: http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(java.lang.String, java.lang.Class)

Vous pouvez également définir un désérialiseur personnalisé lorsque vous instanciez le ObjectMapper: http://wiki.fasterxml.com/JacksonHowToCustomDeserializers

Edit: Je viens de me rappeler autre chose. Si votre objet entrant a plus de propriétés que le POJOa et que vous voulez simplement ignorer les extras, vous voudrez définir ceci:

    objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Ou vous obtiendrez une erreur dans laquelle il ne peut pas trouver la propriété à définir.


Je vais utiliser un CustomDeserializers, ça va me sauver beaucoup de maux de tête! Je pourrai également y appliquer mes stratégies de versioning avec très peu de modifications. Merci!
Alexandre

5
La syntaxe est maintenant: com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper (); mapper.disable (com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
llambda

Bon point @llambda! Je n'ai pas touché à l'ObjectMapper depuis la version 1.7.9, il semble que ma réponse soit dépassée par quelques versions. Vérifiez certainement la version de Jackson que vous utilisez.
Eric Barr

@EricBarr, j'utilise Jackson v1.9.11 et la syntaxe de votre réponse est la bonne pour cette version. Peut-être ont-ils essayé de changer les choses et de les inverser à nouveau dans les versions plus récentes
Ivaylo Slavov

5

Si vous utilisez org.codehaus.jackson, cela est possible depuis la version 1.6. Vous pouvez convertir un JsonNode en POJO avec ObjectMapper#readValue: http://jackson.codehaus.org/1.9.4/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(org.codehaus.jackson.JsonNode , java. lang.Class)


    ObjectMapper mapper = new ObjectMapper();
    JsonParser jsonParser = mapper.getJsonFactory().createJsonParser("{\"foo\":\"bar\"}");
    JsonNode tree = jsonParser.readValueAsTree();
    // Do stuff to the tree
    mapper.readValue(tree, Foo.class);

5
Cette méthode semble manquer dans 2.4.4
Kevin Wittek

1
Voir la réponse d' icedtrees ci-dessous, pour une solution version 2
Tim Büthe


3
String jsonInput = "{ \"hi\": \"Assume this is the JSON\"} ";
com.fasterxml.jackson.databind.ObjectMapper mapper =
    new com.fasterxml.jackson.databind.ObjectMapper();
MyClass myObject = objectMapper.readValue(jsonInput, MyClass.class);

Si votre entrée JSON dans a plus de propriétés que votre POJO et que vous voulez simplement ignorer les extras de Jackson 2.4, vous pouvez configurer votre ObjectMapper comme suit. Cette syntaxe est différente des anciennes versions de Jackson. (Si vous utilisez la mauvaise syntaxe, cela ne fera rien en silence.)

mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNK‌​NOWN_PROPERTIES);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.