2013-10-31 10 views
78

Dies mag ein wenig ungewöhnlich erscheinen, aber ich bin auf der Suche nach einer effizienten Möglichkeit, eine in eine umzuwandeln.Konvertieren JsonNode in POJO

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

Was ich tue ist, laden Sie die JSON-Datei im Speicher in einem JsonNode, wenden Sie ein paar Versionsverwaltungsstrategien an, damit es 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); 

Es wäre denn, es ein schnellerer Weg, es zu tun, werde ich wohl einfach manuell die JsonNodes zu meinem Modell Anwendung am Ende

+0

die Anzahl der Stimmen gegeben definitiv nicht ungewöhnlich. – DPM

Antwort

157

In Jackson 2.4, können Sie konvertieren wie folgt: Sie können eine JsonNode zu einem POJO mit ObjectMapper#readValue konvertieren

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

wo jsonObjectMapper ein Jackson ObjectMapper ist.


In älteren Versionen von Jackson, wäre es

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

Leider gibt es keine TreeToValue (TreeNode n, TypeReference Typ) Variante wie es für readValue() gibt. Schlechte Nachrichten für jeden, der sich mit komplexeren Typen mit Generika beschäftigt :( – Espinosa

+8

@Espinosa Per [jackson-databind # 1294] (https://github.com/FasterXML/jackson-databind/issues/1294), du wirst so etwas wollen (leider ausführlicher) 'jsonObjectMapper.readValue (jsonObjectMapper.treeAsTokens (someJsonNode), someTypeReference)' –

+0

Für ältere Version verwende '' objectMapper.treeToValue (jsonNode, MyClass.class) '' – amod

8

Dieser den Trick tun soll:

mapper.readValue(fileReader, MyClass.class); 

ich sagen soll, weil Ich benutze das mit einer String, nicht eine BufferedReader, aber es sollte immer noch 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 Anruf: http://wiki.fasterxml.com/JacksonHowToCustomDeserializers

Edit:: http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(java.lang.String, java.lang.Class)

Sie auch eine benutzerdefinierte Deserializer definieren können, wenn Sie die ObjectMapper instanziiert Ich habe mich gerade an etwas anderes erinnert. Wenn Ihr Objekt kommt in mehr Eigenschaften hat als die POJO hat und Sie wollen einfach nur die Extras ignorieren Sie diese Einstellung vornehmen wollen:

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

Oder Sie eine Fehlermeldung erhalten, dass es nicht die Eigenschaft finden einbringen.

+0

Ich benutze ein CustomDeserializers, es wird mir eine Menge Kopfschmerzen ersparen! Ich bin auch in der Lage, meine Versionsstrategien dort mit sehr wenig Modifikationen anzuwenden. Vielen Dank! – Alexandre

+2

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

+0

Guter Punkt @labambda! Ich habe den ObjectMapper seit der Version 1.7.9 nicht angefasst, es sieht so aus, als wäre meine Antwort durch einige Versionen veraltet. Überprüfen Sie auf jeden Fall, welche Version von Jackson Sie verwenden. –

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 Ihr JSON Eingang in mehr Eigenschaften als Ihre POJO hat und Sie wollen einfach nur die Extras in Jackson 2.4 ignorieren, können Sie Ihre ObjectMapper wie folgt konfigurieren. Diese Syntax unterscheidet sich von älteren Jackson-Versionen. (Wenn Sie die falsche Syntax verwenden, wird es still nichts tun.)

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

Wenn Sie mit org.codehaus.jackson, dies ist seit 1.6 möglich. 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

Diese Methode scheint zu fehlen in 2.4.4 –

+1

Siehe icedtrees '[Antwort] (http://Stackoverflow.com/a/28714523/60518) unten, für eine Version 2 Lösung –

+0

Die Dokumentation ist jetzt auf https://fasterxml.github.io/jackson-databind/javadoc/2.5/com/fasterxml/jackson/databind/ObjectMapper.html –