我正在使用@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.*中):
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; }
}

使用此配置:
@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);

如您所见,所有者被声明为人类,而不是动物,因此我希望能够省略@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的东西都只能在“动物”中使用。

一种棘手的情况是根值(您直接序列化的值):由于没有声明的类型,它将使用运行时类型。这可能无法按您想要的方式工作。

另一种可能性是对AnnotationIntrospector进行子类化:您也可以在那里更改@JsonTypeInfo的处理方式。只需看看JacksonAnnotationIntrospector的功能,并在适用时覆盖行为即可。

关于java - 将@JsonTypeInfo属性设置为可选,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10905975/

10-10 14:45