我得到了以下课程:
@JsonIdentityInfo(
generator = ObjectIdGenerators.IntSequenceGenerator.class,
property = "oid"
)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "clazz")
@JsonSubTypes({
@JsonSubTypes.Type(value = MySubEntity.class, name = "MySubEntity"),
})
public abstract class Entity {
...
}
public class MySubEntity extends Entity {
...
}
现在,当我序列化包含在MySubEntity
中的Optional
时,JSON不包含包含类型ID的clazz
属性。 错误?当我序列化为List<MySubEntity>
或仅MySubEntity
时,它可以正常工作。
设置:jackson-databind 2.9.4,jackson-datatype-jdk8 2.9.4,序列化在Spring Boot应用程序中完成,提供RESTful Web服务。
编辑:以下是返回Optional
的Spring REST方法:
@RequestMapping(method = RequestMethod.GET, value = "/{uuid}", produces = "application/json")
public Optional<MySubEntity> findByUuid(@PathVariable("uuid") String uuid) {
...
}
修改
我made a SSCCE有一个简单的Spring REST控制器和两个测试。第一个测试直接使用ObjectMapper
,虽然clazz
缺失,但反序列化成功。第二个测试调用REST控制器并因错误而失败,因为缺少clazz
:
提取类型[class com.example.demo.MySubEntity]和内容类型[application / json; charset = UTF-8]的响应时出错;嵌套异常是org.springframework.http.converter.HttpMessageNotReadableException:JSON解析错误:尝试解析[simple type,class com.example.demo.MySubEntity]的子类型时缺少类型id:缺少类型id属性&#39; clazz&# 39 ;;嵌套异常是com.fasterxml.jackson.databind.exc.InvalidTypeIdException:尝试解析[simple type,class com.example.demo.MySubEntity]的子类型时缺少类型id:缺少类型id属性&#39; clazz&#39;
答案 0 :(得分:1)
这确实看起来像一个错误。我可以针对此案例提出一种解决方法,即使用JsonTypeInfo.As.EXISTING_PROPERTY
并将字段clazz
添加到Entity
。这种方法只有一种情况是必须手动在java代码中设置clazz
。然而,这很容易克服。
以下是建议的解决方法的完整代码:
@JsonIdentityInfo(
generator = ObjectIdGenerators.IntSequenceGenerator.class,
property = "oid"
)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY, //field must be present in the POJO
property = "clazz")
@JsonSubTypes({
@JsonSubTypes.Type(value = MySubEntity.class, name = "MySubEntity"),
})
public abstract class Entity {
@JsonProperty
private String uuid;
//Here we have to initialize this field manually.
//Here is the simple workaround to initialize in automatically
@JsonProperty
private String clazz = this.getClass().getSimpleName();
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
}