Converti JsonNode in POJO


143

Questo può sembrare un po 'insolito, ma sto cercando un modo efficiente per trasformare / mappare a JsonNodein POJO.

Conservo alcune delle informazioni del mio modello in file json e devo supportare un paio di versioni del mio modello.

Quello che faccio è caricare il file json in memoria in un JsonNode, applicare un paio di strategie di versioning per farlo corrispondere all'ultima versione del mio modello.

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

A meno che non esista un modo più rapido per farlo, probabilmente finirò semplicemente per applicare manualmente il JsonNodesmio modello

Risposte:


264

In Jackson 2.4, puoi convertire come segue:

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

dov'è jsonObjectMapperun Jackson ObjectMapper.


Nelle versioni precedenti di Jackson, sarebbe

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

18
Sfortunatamente non esiste una variante treeToValue (TreeNode n, TypeReference <T> type) come esiste per readValue (). Cattive notizie per chiunque abbia a che fare con tipi più complessi con generici :(
Espinosa,

13
@Espinosa Per jackson-databind # 1294 , vorrai qualcosa di simile (sfortunatamente più prolisso)jsonObjectMapper.readValue(jsonObjectMapper.treeAsTokens(someJsonNode), someTypeReference)
M. Justin,

Per la versione precedente utilizzare:objectMapper.treeToValue(jsonNode, MyClass.class)
amod

2
È inoltre possibile utilizzare questo metodo in StdDeserializer: p.codec.treeToValue.
galcyurio,

@icedtrees jsonObjectMapper è un'istanza di JsonObjectMapper o solo l'ObjectMapper
KNDheeraj,

8

Questo dovrebbe fare il trucco:

mapper.readValue(fileReader, MyClass.class);

Dico dovrebbe perché lo sto usando con un String, non un BufferedReaderma dovrebbe comunque funzionare.

Ecco il mio codice:

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

Ecco la documentazione ufficiale per quella chiamata: http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(java.lang.String, java.lang.Class)

È inoltre possibile definire un deserializzatore personalizzato quando si crea un'istanza di ObjectMapper: http://wiki.fasterxml.com/JacksonHowToCustomDeserializer

Modifica: ho appena ricordato qualcos'altro. Se il tuo oggetto che arriva ha più proprietà di quello POJOche hai e vuoi solo ignorare gli extra, ti consigliamo di impostare questo:

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

O otterrai un errore che non riesce a trovare la proprietà in cui impostare.


Userò un CustomDeserializer, mi farà risparmiare un sacco di mal di testa! Sarò anche in grado di applicare le mie strategie di versioning lì con pochissime modifiche. Grazie!
Alexandre,

5
La sintassi è ora: com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper (); mapper.disable (com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
llambda,

Buon punto @llambda! Non ho toccato ObjectMapper dalla versione 1.7.9, sembra che la mia risposta non sia aggiornata da alcune versioni. Sicuramente controlla quale versione di Jackson stai usando.
Eric Barr,

@EricBarr, sto usando Jackson v1.9.11 e la sintassi nella tua risposta è quella corretta per quella versione. Forse hanno provato a cambiare le cose e le hanno ripristinate di nuovo nelle versioni più recenti
Ivaylo Slavov,

5

Se stai usando org.codehaus.jackson, questo è possibile dall'1.6. Puoi convertire un JsonNode in un POJO con 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
Questo metodo sembra mancare in 2.4.4
Kevin Wittek il

1
Vedi la risposta di icedtrees di seguito, per una soluzione versione 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);

Se il tuo input JSON ha più proprietà di quelle del tuo POJO e vuoi semplicemente ignorare gli extra in Jackson 2.4, puoi configurare il tuo ObjectMapper come segue. Questa sintassi è diversa dalle versioni precedenti di Jackson. (Se usi la sintassi sbagliata, non farà nulla in silenzio.)

mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNK‌​NOWN_PROPERTIES);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.