Konvertieren Sie JsonNode in POJO

143

Dies mag etwas ungewöhnlich erscheinen, aber ich suche nach einem effizienten Weg, um a JsonNodein a umzuwandeln / abzubilden POJO.

Ich speichere einige Informationen meines Modells in JSON-Dateien und muss einige Versionen meines Modells unterstützen.

Ich lade die JSON-Datei in den Speicher eines JsonNode und wende einige Versionsstrategien an, damit sie mit der neuesten Version meines Modells übereinstimmt.

    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);

Wenn es keinen schnelleren Weg gibt, werde ich das wahrscheinlich einfach manuell JsonNodesauf mein Modell anwenden

Alexandre
quelle

Antworten:

264

In Jackson 2.4 können Sie wie folgt konvertieren:

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

wo jsonObjectMapperist ein Jackson ObjectMapper.


In älteren Versionen von Jackson wäre es

MyClass newJsonNode = jsonObjectMapper.readValue(someJsonNode, MyClass.class);
Eisbäume
quelle
18
Leider gibt es keine Variante von treeToValue (TreeNode n, TypeReference <T>) wie für readValue (). Schlechte Nachrichten für alle, die mit komplexeren Typen mit Generika zu tun haben :(
Espinosa
13
@Espinosa Per Jackson-Datenbank # 1294 möchten Sie etwas wie (leider ausführlicher)jsonObjectMapper.readValue(jsonObjectMapper.treeAsTokens(someJsonNode), someTypeReference)
M. Justin
Für ältere Versionen verwenden Sie: objectMapper.treeToValue(jsonNode, MyClass.class)
amod
2
Sie können diese Methode auch in StdDeserializer verwenden : p.codec.treeToValue.
Galcyurio
@icedtrees jsonObjectMapper ist eine Instanz von JsonObjectMapper oder nur der
ObjectMapper
8

Dies sollte den Trick tun:

mapper.readValue(fileReader, MyClass.class);

Ich sage sollte, weil ich das mit einem benutze, nicht mit einem String, BufferedReaderaber es sollte trotzdem funktionieren.

Hier ist mein Code:

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

Hier ist die offizielle Dokumentation für diesen Aufruf: http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(java.lang.String, java.lang.Class)

Sie können auch einen benutzerdefinierten Deserializer definieren, wenn Sie Folgendes instanziieren ObjectMapper: http://wiki.fasterxml.com/JacksonHowToCustomDeserializers

Edit: Ich habe mich gerade an etwas anderes erinnert. Wenn Ihr eingehendes Objekt mehr Eigenschaften als das POJOhat und Sie nur die Extras ignorieren möchten, möchten Sie Folgendes festlegen:

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

Oder Sie erhalten eine Fehlermeldung, dass die zu setzende Eigenschaft nicht gefunden werden kann.

Eric Barr
quelle
Ich werde einen CustomDeserializer verwenden, das erspart mir viele Kopfschmerzen! Ich werde dort auch meine Versionsstrategien mit sehr geringen Änderungen anwenden können. Vielen Dank!
Alexandre
5
Die Syntax lautet jetzt: com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper (); mapper.disable (com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
Lambda
Guter Punkt @llambda! Ich habe den ObjectMapper seit Version 1.7.9 nicht mehr berührt. Es sieht so aus, als ob meine Antwort um einige Versionen veraltet ist. Überprüfen Sie auf jeden Fall, welche Version von Jackson Sie verwenden.
Eric Barr
@EricBarr, ich verwende Jackson v1.9.11 und die Syntax in Ihrer Antwort ist die richtige für diese Version. Vielleicht haben sie versucht, Dinge zu ändern und sie in den neueren Versionen wieder zurückgesetzt
Ivaylo Slavov
5

Wenn Sie org.codehaus.jackson verwenden, ist dies seit 1.6 möglich. Sie können einen JsonNode in einen POJO konvertieren mit 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);
mumrah
quelle
5
Diese Methode scheint in 2.4.4
Kevin Wittek
1
Siehe die Antwort von icedtrees unten für eine Lösung der Version 2
Tim Büthe
Die Dokumentation ist jetzt unter schnellerxml.github.io/jackson-databind/javadoc/2.5/com/fasterxml/…
David Tonhofer
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);

Wenn Ihre JSON-Eingabe in mehr Eigenschaften als Ihre POJO hat und Sie die Extras in Jackson 2.4 einfach ignorieren möchten, können Sie Ihren ObjectMapper wie folgt konfigurieren. Diese Syntax unterscheidet sich von älteren Jackson-Versionen. (Wenn Sie die falsche Syntax verwenden, wird im Stillen nichts unternommen.)

mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNK‌​NOWN_PROPERTIES);
llambda
quelle