我正在使用Jackson来解析我无法控制的JSON。 JSON看起来像这样:
{
"status":"0"
"type":"type1"
"info": {
// additional fields
}
}
我的班级看起来像这样
public class Response {
private String status;
private String type;
private Info info
}
我使用的Info的子类取决于type属性,因此我对info的映射是
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = Type1Info.class, name = "type1"),
@JsonSubTypes.Type(value = Type2Info.class, name = "type2") })
public abstract class Info {
// some fields
}
据我所知,当区别元素与必须转换的元素处于同一级别时,这是使用类型信息的正确方法。但这不起作用,我总是得到同样的错误:
com.fasterxml.jackson.databind.JsonMappingException:意外的令牌 (END_OBJECT),预期FIELD_NAME:缺少属性'type' 包含类型ID
如果我将EXTERNAL_PROPERTY更改为PROPERTY,我仍然会收到相同的错误。我对EXTERNAL_PROPERTY的理解是错误的吗?
答案 0 :(得分:27)
来自Javadoc:
类似于PROPERTY的包含机制,但属性是 包括层次结构中的一级,即作为兄弟属性 与要输入的JSON对象相同的级别。请注意,此选项只能是 用于属性,不用于类型(类)。试着用它 类将导致基本PROPERTY的包含策略。
注意can only be used for properties
以粗体显示。来源:JsonTypeInfo.As.EXTERNAL_PROPERTY。
因此,您必须将Info
类中的所有注释移至info
类中的属性setInfo
或Response
方法。
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes(value = { @JsonSubTypes.Type(value = Type1Info.class, name = "type1"),
@JsonSubTypes.Type(value = Type2Info.class, name = "type2") })
public void setInfo(Info info) {
this.info = info;
}
对我来说,您还应该从type
课程中移除Response
属性。它将在序列化过程中动态生成。在反序列化中你不需要它,因为杰克逊关心类型。你的课可能是这样的:
class Response {
private String status;
private Info info;
//getters, setters
}
另请参阅此问题:JSON nest class data binding。
答案 1 :(得分:-1)
我找到的最简单的解决方案-将Json与类继承一起使用:
mapper.enableDefaultTyping();
然后,它将在json中为每个对象写入类名, 除非您希望在没有此类信息的情况下看起来漂亮,否则请使用以下解决方案。
这就是我的Json在不同对象的地图上的样子:
{
"key" : [
"com.types.SomeType",
{
"property1" : "a",
"property2" : "b"
}
]
}