Ubah JsonNode menjadi POJO


143

Ini mungkin tampak sedikit tidak biasa, tetapi saya mencari cara yang efisien untuk mengubah / memetakan JsonNodemenjadi POJO.

Saya menyimpan beberapa informasi Model saya dalam file json dan saya harus mendukung beberapa versi model saya.

Apa yang saya lakukan adalah memuat file json di memori dalam JsonNode, menerapkan beberapa strategi versi agar cocok dengan versi terbaru dari Model saya.

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

Kecuali jika ada cara yang lebih cepat untuk melakukannya, saya mungkin akan berakhir hanya dengan menerapkannya secara manual JsonNodeske Model saya

Jawaban:


264

Di Jackson 2.4, Anda dapat mengonversi sebagai berikut:

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

dimana jsonObjectMapperseorang Jackson ObjectMapper.


Dalam versi yang lebih lama dari Jackson, itu akan menjadi

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

18
Sayangnya tidak ada varian treeToValue (TreeNode n, TypeReference <T>) seperti ada untuk readValue (). Berita buruk bagi siapa pun yang berurusan dengan jenis yang lebih kompleks dengan obat generik :(
Espinosa

13
@Espinosa Per jackson-databind # 1294 , Anda akan menginginkan sesuatu seperti (sayangnya lebih bertele-tele)jsonObjectMapper.readValue(jsonObjectMapper.treeAsTokens(someJsonNode), someTypeReference)
M. Justin

Untuk penggunaan versi yang lebih lama:objectMapper.treeToValue(jsonNode, MyClass.class)
amod

2
Anda juga dapat menggunakan metode ini dalam StdDeserializer: p.codec.treeToValue.
galcyurio

@icedtrees jsonObjectMapper adalah turunan dari JsonObjectMapper atau hanya ObjectMapper
KNDheeraj

8

Ini harus melakukan trik:

mapper.readValue(fileReader, MyClass.class);

Saya katakan harus karena saya menggunakan itu dengan String, bukan BufferedReadertetapi itu masih harus bekerja.

Ini kode saya:

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

Berikut dokumentasi resmi untuk panggilan itu: http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(java.lang.String, java.lang.Class)

Anda juga dapat menentukan deserializer khusus ketika Anda instantiate ObjectMapper: http://wiki.fasterxml.com/JacksonHowToCustomDeserializers

Sunting: Saya baru ingat sesuatu yang lain. Jika objek Anda yang masuk memiliki lebih banyak properti daripada yang POJOdimiliki dan Anda hanya ingin mengabaikan ekstra Anda akan ingin mengatur ini:

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

Atau Anda akan mendapatkan kesalahan karena tidak dapat menemukan properti untuk diatur.


Saya akan menggunakan CustomDeserializers, ini akan menyelamatkan saya dari banyak sakit kepala! Saya juga dapat menerapkan strategi versi saya di sana dengan sedikit modifikasi. Terima kasih!
Alexandre

5
Sintaksnya sekarang: com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper (); mapper.disable (com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
llambda

Poin bagus @llambda! Saya belum menyentuh ObjectMapper sejak versi 1.7.9, sepertinya jawaban saya sudah ketinggalan zaman oleh beberapa versi. Periksa versi Jackson yang Anda gunakan.
Eric Barr

@EricBarr, saya menggunakan Jackson v1.9.11 dan sintaks dalam jawaban Anda adalah yang benar untuk versi itu. Mungkin mereka mencoba mengubah sesuatu dan mengembalikannya lagi di versi yang lebih baru
Ivaylo Slavov

5

Jika Anda menggunakan org.codehaus.jackson, ini sudah dimungkinkan sejak 1.6. Anda bisa mengonversi JsonNode menjadi POJO dengan ObjectMapper#readValue: http://jackson.codehaus.org/1.9.4/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(org.codehaus.jackson.JsonNode , java. lang.Kelas)


    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
Metode ini sepertinya tidak ada di 2.4.4
Kevin Wittek

1
Lihat jawaban icedtrees di bawah ini, untuk solusi versi 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);

Jika input JSON Anda memiliki lebih banyak properti daripada POJO Anda dan Anda hanya ingin mengabaikan ekstra di Jackson 2.4, Anda dapat mengonfigurasi ObjectMapper Anda sebagai berikut. Sintaks ini berbeda dari versi Jackson yang lebih lama. (Jika Anda menggunakan sintaks yang salah, itu tidak akan melakukan apa-apa.)

mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNK‌​NOWN_PROPERTIES);
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.