杰克逊版本:2.11.1
我正在尝试将 List 序列化为 json 字符串,然后反序列化它:
public class JacksonTypeTest {
public static abstract class Pet {
final String name;
protected Pet(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static class Dog extends Pet {
public Dog(@JsonProperty("name") String name) {
super(name);
}
}
public static class Cat extends Pet {
public Cat(@JsonProperty("name") String name) {
super(name);
}
}
public static void main(String[] args) throws JsonProcessingException {
List<Pet> pets = new ArrayList<>();
pets.add(new Dog("Dog1"));
pets.add(new Cat("Cat1"));
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator()); // Embed typing data into json
String json = objectMapper.writeValueAsString(pets);
System.out.println(json);
// output: [["com.hyd.jacksontest.JacksonTypeTest$Dog",{"name":"Dog1"}],["com.hyd.jacksontest.JacksonTypeTest$Cat",{"name":"Cat1"}]]
ObjectReader listReader = objectMapper.readerForListOf(Pet.class);
List<Pet> petList = listReader.readValue(json);
// exception: Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException:
// Unexpected token (START_ARRAY), expected VALUE_STRING:
// need JSON String that contains type id (for subtype of java.util.List)
System.out.println(petList);
}
}
它在第
List<Pet> petList = listReader.readValue(json);
行失败,并显示消息:
意外的标记 (START_ARRAY),预期的 VALUE_STRING:需要包含类型 id 的 JSON 字符串(对于 java.util.List 的子类型)
输出:
[["com.hyd.jacksontest.JacksonTypeTest$Dog",{"name":"Dog1"}],["com.hyd.jacksontest.JacksonTypeTest$Cat",{"name":"Cat1"}]]
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_ARRAY), expected VALUE_STRING: need JSON String that contains type id (for subtype of java.util.List)
at [Source: (String)"[["com.hyd.jacksontest.JacksonTypeTest$Dog",{"name":"Dog1"}],["com.hyd.jacksontest.JacksonTypeTest$Cat",{"name":"Cat1"}]]"; line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:1650)
at com.fasterxml.jackson.databind.DeserializationContext.reportWrongTokenException(DeserializationContext.java:1400)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._locateTypeId(AsArrayTypeDeserializer.java:155)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:96)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromArray(AsArrayTypeDeserializer.java:53)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserializeWithType(CollectionDeserializer.java:319)
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:2057)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1496)
at com.hyd.jacksontest.JacksonTypeTest.main(JacksonTypeTest.java:52)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
如何进行反序列化?
好吧,我终于明白了。
问题是,根对象没有类型元数据。
要解决此问题,我需要更改代码:
objectMapper.activateDefaultTyping(
objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL
);
添加第二个参数后,生成的 JSON 字符串如下所示:
["java.util.ArrayList",[["com.hyd.jacksontest.JacksonTypeTest$Dog",{"name":"Dog1"}],["com.hyd.jacksontest.JacksonTypeTest$Cat",{"name":"Cat1"}]]]
这样就可以成功反序列化了。代码现在可以运行了。
您检查过调试正在反序列化的内容吗? json值和你的对象一样吗?
替代代码:
创建一个包含 Pet.class 列表的包装对象类。
如果你不想创建包装类,那么你需要将 json 字符串反序列化为 String 类型的 List 并循环遍历该列表,将字符串反序列化为 Pet 类。
List <String> petJsons = new ArrayList <> ();
petJsons = mapper.readValue(json, List.class);
for (Iterator <String> iterator = petJsons.iterator(); iterator.hasNext();) {
String petJson = (String) iterator.next();
pets.add(objectMapper.objectMapper.readValue(petJson, Pet.class));
}