我正在使用 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:缺少属性“类型”,即 包含类型 ID
如果我将 EXTERNAL_PROPERTY 更改为 PROPERTY 我仍然会遇到相同的错误。难道我对EXTERNAL_PROPERTY的理解有误?
来自 Javadoc:
类似于PROPERTY的包含机制,只不过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
属性。它将在序列化过程中动态生成。在反序列化中你不需要它,因为 Jackson 关心类型。你的课程可能是这样的:
class Response {
private String status;
private Info info;
//getters, setters
}
另请参阅这个问题:JSON 嵌套类数据绑定。
对于所有使用 AutoValue 或任何其他 源代码生成器 的人:当您注释抽象方法(在生成的代码中返回实际属性)时,@JsonTypeInfo 和 @JsonSubTypes 注释不起作用。 如果你这样做,你会得到以下异常:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of [xxx] (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
当您在注释为 @JsonCreator 的方法中注释参数时,它也不起作用。如果你这样做,你会得到这个奇怪的异常:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class [xxx]
因此,要处理它,只需不要使用此类的源代码生成器,只需使用常见的杰克逊注释映射
Response
对象:@JsonCreator,@JsonProperty和@JsonTypeInfo,@JsonSubTypes
使用 Jackson 2.10.5 进行测试