java 使 @JsonTypeInfo 属性可选
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10905975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Make @JsonTypeInfo property optional
提问by Mark Peters
I'm using @JsonTypeInfo
to instruct Hymanson to look in the @class
property for concrete type information. However, sometimes I don't want to have to specify @class
, particularly when the subtype can be inferred given the context. What's the best way to do that?
我@JsonTypeInfo
用来指示 Hymanson 在@class
属性中查找具体类型信息。但是,有时我不想指定@class
,特别是当可以根据上下文推断子类型时。 最好的方法是什么?
Here's an example of the JSON:
这是 JSON 的示例:
{
"owner": {"name":"Dave"},
"residents":[
{"@class":"Hymansonquestion.Dog","breed":"Greyhound"},
{"@class":"Hymansonquestion.Human","name":"Cheryl"},
{"@class":"Hymansonquestion.Human","name":"Timothy"}
]
}
and I'm trying to deserialize them into these classes (all in Hymansonquestion.*
):
我正在尝试将它们反序列化为这些类(全部在 中Hymansonquestion.*
):
public class Household {
private Human owner;
private List<Animal> residents;
public Human getOwner() { return owner; }
public void setOwner(Human owner) { this.owner = owner; }
public List<Animal> getResidents() { return residents; }
public void setResidents(List<Animal> residents) { this.residents = residents; }
}
public class Animal {}
public class Dog extends Animal {
private String breed;
public String getBreed() { return breed; }
public void setBreed(String breed) { this.breed = breed; }
}
public class Human extends Animal {
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
using this config:
使用这个配置:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
private static class AnimalMixin {
}
//...
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.getDeserializationConfig().addMixInAnnotations(Animal.class, AnimalMixin.class);
Household household = objectMapper.readValue(json, Household.class);
System.out.println(household);
As you can see, the owner is declared as a Human, not an Animal, so I want to be able to omit @class
and have Hymanson infer the type as it normally would.
如您所见,所有者被声明为人类,而不是动物,因此我希望能够@class
像往常一样省略并让Hyman逊推断类型。
When I run this though, I get
当我运行这个时,我得到
org.codehaus.Hymanson.map.JsonMappingException: Unexpected token (END_OBJECT),
expected FIELD_NAME: missing property '@class' that is to contain type id (for class Hymansonquestion.Human)
Since "owner" doesn't specify @class
.
由于“所有者”没有指定@class
.
Any ideas? One initial thought I had was to use @JsonTypeInfo
on the property rather than the type. However, this cannot be leveraged to annotate the element type of a list.(Incorrect, see answer)
有任何想法吗?我最初的一个想法是使用@JsonTypeInfo
属性而不是类型。 但是,这不能用于注释列表的元素类型。(不正确,见答案)
采纳答案by StaxMan
You probably should not actually do this -- it seems like a micro-optimization for special cases, complicating life -- but if you really think you do want to, you can try adding @JsonTypeInfo
override on Human. Annotations are inheritable in Hymanson, and you can override definitions. In this case which one gets used then depends on declared type: so anything declared as Human
would see annotation on Human
; and anything declared as Animal
only one in `Animal.
您可能实际上不应该这样做——这似乎是对特殊情况的微优化,使生活复杂化——但如果你真的认为你愿意,你可以尝试@JsonTypeInfo
在 Human 上添加覆盖。注释在 Hymanson 中是可继承的,您可以覆盖定义。在这种情况下,使用哪个取决于声明的类型:因此声明为的任何内容Human
都会在Human
;上看到注释。以及任何Animal
在“Animal”中声明为唯一的东西。
One tricky case is the root value (value you directly serialize): since there is no declared type, it will use the runtime type. And this will probably not work the way you want.
一个棘手的情况是根值(您直接序列化的值):由于没有声明类型,它将使用运行时类型。这可能不会以您想要的方式工作。
Another possibility is sub-classing AnnotationIntrospector
: you can change the handling of @JsonTypeInfo
there as well; just see what HymansonAnnotationIntrospector
does, override behavior as applicable.
另一种可能性是子类化AnnotationIntrospector
:您也可以更改@JsonTypeInfo
那里的处理方式;看看有什么HymansonAnnotationIntrospector
作用,根据情况覆盖行为。
回答by Mark Peters
So it turns out that I had misunderstood the Javadoc for @JsonTypeInfo
. When I said in my question
所以事实证明我误解了Javadoc 的@JsonTypeInfo
. 当我在我的问题中说
One initial thought I had was to use @JsonTypeInfo on the property rather than the type. However, this cannot be leveraged to annotate the element type of a list.
我最初的一个想法是在属性上使用 @JsonTypeInfo 而不是类型。但是,这不能用于注释列表的元素类型。
I was basing that on this quote from the Javadoc:
我是基于 Javadoc 中的这句话:
When used for properties (fields, methods), this annotation applies to values: so when applied to structure types (like Collection, Map, arrays), will apply to contained values, not the container; for non-structured types there is no difference. (...) There is no per-property way to force type information to be included for type of container (structured type); for container types one has to use annotation for type declaration.
当用于属性(字段、方法)时,此注释适用于值:因此,当应用于结构类型(如 Collection、Map、数组)时,将应用于包含的值,而不是容器;对于非结构化类型,没有区别。(...) 没有针对每个属性的方法来强制包含容器类型(结构化类型)的类型信息;对于容器类型,必须使用注释进行类型声明。
I somehow misread that to mean the opposite; that the type info would apply to the container and not the elements. Obviously that was wrong. So I was able to fix this by using the following:
我不知何故误读了相反的意思;类型信息将应用于容器而不是元素。显然这是错误的。所以我能够通过使用以下方法来解决这个问题:
public class Household {
//...
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public void setResidents(List<Animal> residents) {
this.residents = residents;
}
}
Now @class
is only required for Animals that are specified in the residents
property.
Now@class
仅对residents
属性中指定的 Animals 是必需的。