Deserialize String เป็น List of Strings
ฉันมี POJO ที่มีคุณสมบัติดังต่อไปนี้
public class Example {
@JsonProperty("inputFoo")
private String foo
@JsonProperty("inputBar")
private String bar
@JsonProperty("inputBaz")
@JsonDeserialize(using = MyDeserializer.class)
private Set<String> baz
}
JSON ที่ฉันใช้เพื่อแสดงข้อมูลนี้ในปัจจุบันแสดงถึงแอตทริบิวต์ baz เป็นสตริงเดียว:
{"inputFoo":"a", "inputBar":"b", "inputBaz":"c"}
ฉันใช้ Jackson ObjectMapper เพื่อพยายามแปลง JSON เป็น POJO ของฉัน ฉันรู้ว่า input baz String จาก JSON เคยชินแมปไปยัง Set ที่ฉันพยายามจะแทนมันดังนั้นฉันจึงกำหนด Deserializer แบบกำหนดเอง:
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;
}
}
ฉันได้รับ IllegalArgumentException ที่อ้างถึงแอตทริบิวต์ "inputBaz" ซึ่งฉันสามารถให้รายละเอียดได้ มีใครเห็นปัญหาที่ชัดเจนเกี่ยวกับการใช้งาน deserializer ของฉันบ้าง ขอบคุณ
คำตอบ
คุณไม่จำเป็นต้องติดตั้ง deserialiser ที่กำหนดเองใช้คุณลักษณะACCEPT_SINGLE_VALUE_AS_ARRAY มันใช้ได้กับชุดเช่นกัน:
คุณลักษณะที่พิจารณาว่าสามารถบังคับค่าที่ไม่ใช่อาร์เรย์ (ใน JSON) เพื่อทำงานกับชนิดคอลเลกชัน Java (อาร์เรย์, java.util.Collection)ได้หรือไม่ หากเปิดใช้งานคอลเลกชัน deserializers จะพยายามจัดการค่าที่ไม่ใช่อาร์เรย์ราวกับว่ามี "โดยนัย" รอบอาร์เรย์ JSON คุณลักษณะนี้มีไว้เพื่อใช้สำหรับเหตุผลด้านความเข้ากันได้ / ความสามารถในการทำงานร่วมกันเพื่อทำงานกับแพ็คเกจ (เช่นตัวแปลง XML เป็น JSON) ที่เว้นอาร์เรย์ JSON ในกรณีที่มีเพียงองค์ประกอบเดียวในอาร์เรย์ คุณลักษณะถูกปิดใช้งานโดยค่าเริ่มต้น
ดูสิ่งนี้ด้วย:
- com.fasterxml.jackson.databind.exc.MismatchedInputException: ไม่สามารถ deserialize อินสแตนซ์java.util.ArrayListจากโทเค็น START_OBJECT
แทนที่ตัวสร้าง 2 ตัวด้วยตัวสร้างที่ไม่มีอาร์กิวเมนต์นี้:
public MyDeserializer() {
super(TypeFactory.defaultInstance().constructCollectionType(Set.class, String.class));
}
ACCEPT_SINGLE_VALUE_AS_ARRAY ตามที่แนะนำเป็นตัวเลือกที่ดี
บางทีปัญหาที่แท้จริงของคุณอาจซับซ้อนกว่านี้ แต่หากไม่เป็นเช่นนั้นคุณสามารถลอง@JsonCreatorแทน deserializer แบบกำหนดเองได้ ชอบ:
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;
}
เพียงเพื่อแสดงให้เห็นว่าในกรณีทั่วไปคุณอาจหลีกเลี่ยงการใช้ deserializer ที่กำหนดเองด้วย@JsonCreatorแต่ยังคงทำการแปลงแบบง่ายๆ