Saya mencoba memasukkan JSON mentah di dalam objek Java ketika objek tersebut (de) diserialisasi menggunakan Jackson. Untuk menguji fungsionalitas ini, saya menulis tes berikut:
public static class Pojo {
public String foo;
@JsonRawValue
public String bar;
}
@Test
public void test() throws JsonGenerationException, JsonMappingException, IOException {
String foo = "one";
String bar = "{\"A\":false}";
Pojo pojo = new Pojo();
pojo.foo = foo;
pojo.bar = bar;
String json = "{\"foo\":\"" + foo + "\",\"bar\":" + bar + "}";
ObjectMapper objectMapper = new ObjectMapper();
String output = objectMapper.writeValueAsString(pojo);
System.out.println(output);
assertEquals(json, output);
Pojo deserialized = objectMapper.readValue(output, Pojo.class);
assertEquals(foo, deserialized.foo);
assertEquals(bar, deserialized.bar);
}
Kode mengeluarkan baris berikut:
{"foo":"one","bar":{"A":false}}
JSON persis seperti yang saya inginkan. Sayangnya, kode gagal dengan pengecualian saat mencoba membaca JSON kembali ke objek. Berikut pengecualiannya:
org.codehaus.jackson.map.JsonMappingException: Tidak dapat mendelialisasi instance java.lang.String dari token START_OBJECT di [Sumber: java.io.StringReader@d70d7a; baris: 1, kolom: 13] (melalui rantai referensi: com.tnal.prism.cobalt.gather.testing.Pojo ["bar"])
Mengapa Jackson berfungsi dengan baik di satu arah tetapi gagal saat pergi ke arah lain? Sepertinya itu harus dapat mengambil keluarannya sendiri sebagai masukan lagi. Saya tahu apa yang saya coba lakukan tidak ortodoks (saran umumnya adalah membuat objek dalam bar
yang memiliki properti bernama A
), tetapi saya sama sekali tidak ingin berinteraksi dengan JSON ini. Kode saya bertindak sebagai penerusan untuk kode ini - Saya ingin mengambil JSON ini dan mengirimkannya kembali tanpa menyentuh apa pun, karena ketika JSON berubah, saya tidak ingin kode saya perlu dimodifikasi.
Terima kasih atas sarannya.
EDIT: Menjadikan Pojo kelas statis, yang menyebabkan kesalahan berbeda.
sumber
Mengikuti jawaban @StaxMan , saya telah membuat karya berikut seperti pesona:
Dan, untuk setia pada pertanyaan awal, inilah tes kerjanya:
sumber
getJson()
mengembalikan aString
. Jika itu hanya mengembalikanJsonNode
yang telah ditetapkan melalui penyetel, itu akan diserialkan seperti yang diinginkan, bukan?node.asText()
mengembalikan nilai kosong yang berlawanantoString()
.Saya bisa melakukan ini dengan deserializer khusus (dipotong dan ditempel dari sini )
sumber
@JsonRawValue
@Jsonter dapat membantu. Lihat contoh saya ('data' seharusnya berisi JSON yang tidak diurai):
sumber
Menambah jawaban bagus Roy Truelove , berikut adalah cara menyuntikkan custom deserialiser sebagai respons terhadap tampilan :
@JsonRawValue
sumber
Ini adalah masalah dengan kelas batin Anda. The
Pojo
kelas adalah kelas batin non-statis kelas pengujian Anda, dan Jackson tidak bisa instantiate kelas. Jadi itu bisa membuat serial, tapi tidak deserialize.Definisikan ulang kelas Anda seperti ini:
Perhatikan penambahan
static
sumber
Solusi mudah ini berhasil untuk saya:
Jadi saya bisa menyimpan nilai mentah JSON dalam variabel rawJsonValue dan kemudian tidak ada masalah untuk menghilangkannya (sebagai objek) dengan bidang lain kembali ke JSON dan mengirim melalui REST saya. Menggunakan @JsonRawValue tidak membantu saya karena JSON yang disimpan dideserialisasi sebagai String, bukan sebagai objek, dan bukan itu yang saya inginkan.
sumber
Ini bahkan berfungsi di entitas JPA:
Idealnya ObjectMapper dan bahkan JsonFactory berasal dari konteks dan dikonfigurasi untuk menangani JSON Anda dengan benar (standar atau dengan nilai non-standar seperti float 'Infinity' misalnya).
sumber
JsonNode.toString()
dokumentasiMethod that will produce developer-readable representation of the node; which may <b>or may not</b> be as valid JSON.
Jadi ini sebenarnya implementasi yang sangat berisiko.JsonNode.asText()
internal dan akan mengeluarkan Infinity dan nilai JSON non-standar lainnya.Berikut adalah contoh kerja lengkap tentang cara menggunakan modul Jackson untuk membuat
@JsonRawValue
pekerjaan dua arah (serialisasi dan deserialisasi):Kemudian Anda dapat mendaftarkan modul setelah membuat
ObjectMapper
:sumber
org.codehaus.jackson
paket tanpa menyadarinya. Pastikan semua impor Anda berasalcom.fasterxml.jackson
.Saya memiliki masalah yang sama persis. Saya menemukan solusinya dalam posting ini: Parse JSON tree ke kelas biasa menggunakan Jackson atau alternatifnya
Lihat jawaban terakhir. Dengan menentukan penyetel khusus untuk properti yang menggunakan JsonNode sebagai parameter dan memanggil metode toString di jsonNode untuk menyetel properti String, semuanya berhasil.
sumber
Menggunakan objek bekerja dengan baik dua arah ... Metode ini memiliki sedikit overhead deserialisasi nilai mentah dalam dua kali.
RawHello.java
RawJsonValue.java
sumber
Saya memiliki masalah serupa, tetapi menggunakan daftar dengan banyak itens JSON (
List<String>
).Saya mengelola serialisasi menggunakan
@JsonRawValue
anotasi. Tapi untuk deserialization saya harus membuat custom deserializer berdasarkan saran Roy.Di bawah ini Anda dapat melihat deserializer "Daftar" saya.
sumber