Bagaimana cara mengurai string JSON ke JsonNode di Jackson?

231

Seharusnya sangat sederhana, tapi aku tidak bisa menemukannya setelah mencoba selama satu jam #membuat.

Saya perlu mendapatkan string JSON, misalnya {"k1":v1,"k2":v2},, diuraikan sebagai a JsonNode.

JsonFactory factory = new JsonFactory();
JsonParser jp = factory.createJsonParser("{\"k1\":\"v1\"}");
JsonNode actualObj = jp.readValueAsTree();

memberi

java.lang.IllegalStateException: No ObjectCodec defined for the parser, can not deserialize JSON into JsonNode tree

fadmaa
sumber
54
#embarrasing- tidak. Jika hal-hal sederhana tidak sederhana, maka perancang API telah gagal, bukan Anda.
jameshfisher
@ StaxMan jawaban dalam kode: JsonFactory factory = new MappingJsonFactory ();
Juan Rojas

Jawaban:

371

Sedikit variasi pada jawaban Richards tetapi readTreedapat mengambil string sehingga Anda dapat menyederhanakannya menjadi:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree("{\"k1\":\"v1\"}");
Slashnick
sumber
44
Bagi siapa saja yang membutuhkan ObjectNodedaripada JsonNodemenggunakanmapper.valueToTree("{\"k1\":\"v1\"}")
Matius Herbst
5
@MatthewHerbst Di 2.5.1, ini membuat simpul teks baru dengan string "{\" k1 \ ": \" v1 \ "}" daripada mem-parsingnya sebagai JSON.
minexew
69

Anda perlu menggunakan ObjectMapper:

ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = mapper.getJsonFactory(); // since 2.1 use mapper.getFactory() instead
JsonParser jp = factory.createJsonParser("{\"k1\":\"v1\"}");
JsonNode actualObj = mapper.readTree(jp);

Dokumentasi lebih lanjut tentang membuat parser dapat ditemukan di sini .

Richard Fearn
sumber
Apakah mungkin untuk mengambil JsonNode, memodifikasinya sedikit, dan kemudian memanggil mapper.readValue (node, class); dan keluar kelas?
portforwardpodcast
1
Iya. Bahkan ada alias untuk itu mapper.treeToValue(),. Tetapi readValue()juga berhasil.
StaxMan
Tautan itu tampaknya rusak
manuna
28

Varian ketiga:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readValue("{\"k1\":\"v1\"}", JsonNode.class);
qerub
sumber
Apa yang sebenarnya lewat di JsonNode.class membawa Anda ke sini?
David
3
@ David: Tidak ada, jadi varian slashnick jelas lebih baik jika Anda hanya menginginkan a JsonNode. Namun, Anda biasanya tidak menginginkannya JsonNode, jadi saya ingin menunjukkan bagaimana cara memberi tahu Jackson nilai seperti apa yang Anda inginkan.
qerub
Bagi saya, passing JsonNodetampaknya perlu untuk mencegah Jackson deserialisasi sebagai sesuatu yang lain - yang akan gagal.
Cory Klein
5

Jawaban Richard benar. Atau Anda juga dapat membuat MappingJsonFactory(di org.codehaus.jackson.map) yang tahu di mana menemukannya ObjectMapper. Kesalahan yang Anda dapatkan adalah karena reguler JsonFactory(dari corepaket) tidak memiliki ketergantungan ke ObjectMapper(yang ada dalam mapperpaket).

Tetapi biasanya Anda hanya menggunakan ObjectMapperdan tidak mengkhawatirkan JsonParseratau komponen tingkat rendah lainnya - mereka hanya akan diperlukan jika Anda ingin mengikat bagian-bagian aliran data, atau melakukan penanganan tingkat rendah.

StaxMan
sumber
3
import com.github.fge.jackson.JsonLoader;
JsonLoader.fromString("{\"k1\":\"v1\"}")
== JsonNode = {"k1":"v1"}
pdxleif
sumber
0

Pendekatan baru terhadap pertanyaan lama. Solusi yang berfungsi dari java 9+

ObjectNode agencyNode = new ObjectMapper().valueToTree(Map.of("key", "value"));

lebih mudah dibaca dan dipelihara untuk objek yang kompleks. Ej

Map<String, Object> agencyMap = Map.of(
        "name", "Agencia Prueba",
        "phone1", "1198788373",
        "address", "Larrea 45 e/ calligaris y paris",
        "number", 267,
        "enable", true,
        "location", Map.of("id", 54),
        "responsible", Set.of(Map.of("id", 405)),
        "sellers", List.of(Map.of("id", 605))
);
ObjectNode agencyNode = new ObjectMapper().valueToTree(agencyMap);
Manuel Ortiz
sumber