Deserialisasi String sebagai Daftar String
Saya memiliki POJO yang berisi atribut berikut
public class Example {
@JsonProperty("inputFoo")
private String foo
@JsonProperty("inputBar")
private String bar
@JsonProperty("inputBaz")
@JsonDeserialize(using = MyDeserializer.class)
private Set<String> baz
}
JSON yang saya kerjakan untuk mewakili data ini saat ini mewakili atribut baz sebagai string tunggal:
{"inputFoo":"a", "inputBar":"b", "inputBaz":"c"}
Saya menggunakan Jackson ObjectMapper untuk mencoba mengubah JSON menjadi POJO saya. Saya tahu bahwa input baz String dari JSON tidak akan dipetakan dengan bersih ke Set yang saya coba wakili sebagai, jadi saya mendefinisikan Deserializer kustom:
public class MyDeserializer extends StdDeserializer<Set<String>> {
public MyDeserializer(){}
public MyDeserializer(Class<?> vc) {
super(vc);
}
public Set<String> deserialize(JsonParser p, DeserializationContext cxt) throws IOException, JsonProcessingException {
String input = p.readValueAs(String.class);
Set<String> output = new HashSet<>();
if(input != null) {
output.add(input);
}
return output;
}
}
Saya mendapatkan IllegalArgumentException yang merujuk pada atribut "inputBaz", yang dapat saya berikan detailnya. Apakah ada yang melihat masalah yang jelas dengan penerapan deserializer saya? Terima kasih
Jawaban
Anda tidak perlu menerapkan deserialiser khusus, gunakan fitur ACCEPT_SINGLE_VALUE_AS_ARRAY . Ini berfungsi untuk set juga:
Fitur yang menentukan apakah boleh memaksa nilai non-array (dalam JSON) untuk bekerja dengan jenis koleksi Java (array, java.util.Collection) . Jika diaktifkan, penghapus serial koleksi akan mencoba menangani nilai non-larik seolah-olah memiliki "implisit" di sekitar larik JSON. Fitur ini dimaksudkan untuk digunakan untuk alasan kompatibilitas / interoperabilitas, untuk bekerja dengan paket (seperti konverter XML-ke-JSON) yang meninggalkan larik JSON dalam kasus di mana hanya ada satu elemen dalam larik. Fitur dinonaktifkan secara default.
Lihat juga:
- com.fasterxml.jackson.databind.exc.MismatchedInputException: Tidak dapat menghapus nama instance dari java.util.ArrayListtoken START_OBJECT
Ganti 2 konstruktor dengan konstruktor no-arg ini:
public MyDeserializer() {
super(TypeFactory.defaultInstance().constructCollectionType(Set.class, String.class));
}
ACCEPT_SINGLE_VALUE_AS_ARRAY seperti yang disarankan adalah pilihan yang baik.
Mungkin masalah Anda sebenarnya lebih rumit tetapi jika tidak Anda juga bisa mencoba @JsonCreatorsebagai pengganti deserializer kustom. Suka:
public class Example {
@JsonCreator
public Example(@JsonProperty("inputFoo") String foo,
@JsonProperty("inputBar") String bar,
@JsonProperty("inputBaz") String strBaz) {
this.foo = foo;
this.bar = bar;
this.baz = new HashSet<>();
baz.add(strBaz);
}
private String foo;
private String bar;
private Set<String> baz;
}
Hanya untuk menunjukkan bahwa dalam kasus yang lebih umum Anda mungkin menghindari penerapan deserializer kustom @JsonCreatorjuga tetapi tetap membuat beberapa konversi sederhana.