当我尝试再次序列化和重新序列化泛型类型Jackson中的List时失败。
有一个JDoodle,如果你想玩一个工作的例子:https://jdoodle.com/a/6nJ4
这是我的泛型类
public static class UserMessageResult<T> {
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
private T entity;
public UserMessageResult() {
}
public UserMessageResult(T entity) {
this.entity = entity;
}
}
这个类在列表中用作泛型
@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY)
public static class AnEntity {
private int anInt;
private String aString;
public AnEntity() {
}
public AnEntity(int anInt, String aString) {
this.anInt = anInt;
this.aString = aString;
}
public int getAnInt() {
return anInt;
}
public String getaString() {
return aString;
}
}
如果我将AnEntity
放入List
中,并将此列表添加到UserMessageResult
中,则Jackson无法读取它刚刚创建的JSON。
List<AnEntity> anEntityList= List.of(
new AnEntity(10, "aaa"),
new AnEntity(20, "bbb")
);
UserMessageResult<List<AnEntity>> userMessageResult = new UserMessageResult(anEntityList);
System.out.println(userMessageResult);
String jsonStr = MAPPER.writeValueAsString(userMessageResult);
System.out.println(jsonStr);
final TypeReference<UserMessageResult<List<AnEntity>>> typeRef = new TypeReference<>() {
};
UserMessageResult<List<AnEntity>> actualUserMessageResult = MAPPER.readValue(jsonStr, typeRef);
System.out.println(actualUserMessageResult);
错误消息
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class MyClass$AnEntity]: missing type id property '@class' (for POJO property 'entity')
at [Source: (String)"{
"entity" : [ "java.util.ImmutableCollections$List12", [ {
"anInt" : 10,
"aString" : "aaa"
}, {
"anInt" : 20,
"aString" : "bbb"
} ] ]
}"; line: 2, column: 16] (through reference chain: MyClass$UserMessageResult["entity"]->java.util.ArrayList[0])
at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43)
at com.fasterxml.jackson.databind.DeserializationContext.missingTypeIdException(DeserializationContext.java:2094)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingTypeId(DeserializationContext.java:1607)
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._handleMissingTypeId(TypeDeserializerBase.java:307)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:211)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:122)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1296)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:361)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4825)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3772)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3755)
at MyClass.listOfEntities(MyClass.java:57)
at MyClass.main(MyClass.java:21)
显然,列表项中的@class属性丢失了。如果我手动更改JSON并添加@class属性,一切都正常:
System.out.println("+++++++++++++++++ Manualy corrected JSON +++++++++++++++++");
String jsonStr = """
{
"entity" : [ {
"@class" : "MyClass$AnEntity",
"anInt" : 10,
"aString" : "String 1"
}, {
"@class" : "MyClass$AnEntity",
"anInt" : 20,
"aString" : "String 2"
} ]
}
""";
final TypeReference<UserMessageResult<List<AnEntity>>> typeRef = new TypeReference<>() {
};
UserMessageResult<?> actualUserMessageResult = MAPPER.readValue(jsonStr, typeRef);
System.out.println( actualUserMessageResult);
我用的是Jackson2.15.这在Jackson2.14版之前一直正常工作。使用和不使用@JsonTypeInfo注解并没有改变任何东西。
有什么想法吗?
1条答案
按热度按时间mo49yndu1#
1.当你通过使用
TypeReference
告诉解析器你的对象的类型时,只需要删除@JsonTypeInfo
注解和你的listOfEntities()
代码(你首先序列化它,然后再序列化结果json String)就会开始工作。1.如果你想保持类型信息存储在序列化的字符串中,而不是
TypeReference
,只使用原始类型:我检查了我的编译器中的两个替代方案和两个工作。
令人惊讶的是,你在jdoodle代码中的“手动更正”
deserializeJson()
方法对我不起作用。这里我得到一个错误:在Sping Boot 3.1.1下测试,Jackson依赖由Sping Boot parent管理: