Java 将@JsonTypeInfo属性设置为可选
我使用Java 将@JsonTypeInfo属性设置为可选,java,json,jackson,Java,Json,Jackson,我使用@JsonTypeInfo指示Jackson在@class属性中查找具体的类型信息。但是,有时我不想必须指定@class,特别是当可以根据上下文推断子类型时最好的方法是什么? 以下是JSON的一个示例: { "owner": {"name":"Dave"}, "residents":[ {"@class":"jacksonquestion.Dog","breed":"Greyhound"}, {"@class":"jacksonquesti
@JsonTypeInfo
指示Jackson在@class
属性中查找具体的类型信息。但是,有时我不想必须指定@class
,特别是当可以根据上下文推断子类型时最好的方法是什么?
以下是JSON的一个示例:
{
"owner": {"name":"Dave"},
"residents":[
{"@class":"jacksonquestion.Dog","breed":"Greyhound"},
{"@class":"jacksonquestion.Human","name":"Cheryl"},
{"@class":"jacksonquestion.Human","name":"Timothy"}
]
}
我正试图将它们反序列化为这些类(都在jacksonquestion.*
):
如您所见,所有者被声明为人类,而不是动物,因此我希望能够省略@class
,并让Jackson按照正常情况推断类型
当我运行这个程序时,我会
org.codehaus.jackson.map.JsonMappingException: Unexpected token (END_OBJECT),
expected FIELD_NAME: missing property '@class' that is to contain type id (for class jacksonquestion.Human)
因为“所有者”没有指定@class
有什么想法吗?我最初的想法是对属性而不是类型使用
@JsonTypeInfo
。但是,这不能用于注释列表的元素类型。(不正确,请参见答案)您可能不应该实际执行此操作——这似乎是针对特殊情况的微观优化,使生活变得复杂——但如果您确实认为您愿意,您可以尝试在Human上添加@JsonTypeInfo
覆盖。注释在Jackson中是可继承的,您可以覆盖定义。在这种情况下,使用哪一个取决于声明的类型:因此任何声明为Human
的内容都会在Human
上看到注释;任何声明为动物的东西
只有一个在'Animal'中
一个棘手的情况是根值(直接序列化的值):由于没有声明的类型,它将使用运行时类型。这可能不会按你想要的方式工作
另一种可能是子分类
注释Introspector
:您也可以在那里更改@JsonTypeInfo
的处理方式;看看JacksonAnnotationIntrospector做了什么,在适用的情况下覆盖行为。所以我误解了。当我在问题中说
我最初的想法是在属性上使用@JsonTypeInfo,而不是在类型上。但是,这不能用于注释列表的元素类型
我是基于Javadoc的这句话:
当用于属性(字段、方法)时,此注释应用于值:因此,当应用于结构类型(如集合、映射、数组)时,将应用于包含的值,而不是容器;对于非结构化类型,没有区别。(…)没有每个属性的方法强制包含容器类型(结构化类型)的类型信息;对于容器类型,必须使用注释进行类型声明
我不知何故误读了这句话,以为它的意思正好相反;类型信息将应用于容器而不是元素。显然这是错误的。因此,我可以通过以下方法解决此问题:
public class Household {
//...
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public void setResidents(List<Animal> residents) {
this.residents = residents;
}
}
公共类家庭{
//...
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS,include=JsonTypeInfo.As.PROPERTY,PROPERTY=“@CLASS”)
公屋居民(名单居民){
这个。居民=居民;
}
}
现在,
@class
仅适用于居民
属性中指定的动物。谢谢您的回答。在人类身上覆盖类型是我探索的一条途径,但是(如果我没记错的话)我遇到了我认为你在第二段中描述的问题……当时我试图在列表中包含人类
,它抱怨道。我将发布一个关于我如何解决这个问题的答案,但是如果我想继续沿着“可选注释”路径走下去,AnnotationIntrospector看起来是一条有价值的路径。FWIW,这种方式(应用于元素)受到JAXB的严重影响,JAXB具有这种行为。没错,我在上面省略的Javadoc部分包括“这与JAXB处理类型信息注释的方式相同;选择它是因为它是主要的用例。”我同意它是主要的用例。
org.codehaus.jackson.map.JsonMappingException: Unexpected token (END_OBJECT),
expected FIELD_NAME: missing property '@class' that is to contain type id (for class jacksonquestion.Human)
public class Household {
//...
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public void setResidents(List<Animal> residents) {
this.residents = residents;
}
}