【发布时间】:2019-04-24 13:57:57
【问题描述】:
我正在尝试使用 Jackson 反序列化一些多态对象,但我不想在 JSON 中公开类型信息。所以,假设我们有“经典”动物场景:
public interface Animal {
String talk();
}
public class Dog implements Animal {
public String talk() { return "Woof!"; }
}
public class Cat implements Animal {
public String talk() { return "Meow!"; }
}
我还有一个 Factory 接口和多个 Factory 实现:
public interface AnimalFactory {
Animal newAnimal();
}
public class DogFactory implements AnimalFactory {
public Animal newAnimal() { return new Dog(); }
}
public class CatFactory implements AnimalFactory {
public Animal newAnimal() { return new Cat(); }
}
由于我不想通过在 JSON 中使用 @JsonTypeInfo 和 type 参数来污染 JSON 的实现细节,所以我只知道两种选择:
- 在
Animal上使用@JsonDeserialize(as = Dog.class),但这需要从API 到实现类的显式依赖;此外,它总是将 JSON 反序列化为 Dog,而我只想在运行时找到合适的具体实现,因为我不知道哪个具体实现可用; - 使用
StdDeserializer子类:
public class AnimalDeserializer extends StdDeserializer<Animal> {
// Obtain through dependency injection or other mechanism
private AnimalFactory animalFactory;
public AnimalDeserializer() {
this(null);
}
public AnimalDeserializer(Class<Animal> vc) {
super(vc);
}
@Override
public Animal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return animalFactory.newAnimal();
}
这种方法可以让我在运行时定位实现,但它也需要我手动设置和获取任何字段,而不是依赖数据绑定(当然在这种特定情况下这将是微不足道的,但我的对象非常复杂而且我还有很多不同的接口,所以我真的需要依赖数据绑定)。
所以,我的问题是:我是否有另一种手动提供具体 Animal 实例的方法,然后让杰克逊执行其数据绑定魔术,而不是手动实现所有这些?作为参考,如果有人对 JAXB 有一定的经验,像 @XmlRegistry 这样我可以为给定接口指定工厂的东西会很棒。
谢谢!
编辑:可能不是很清楚,但我不想在 JSON 中放置 type 属性以进行反序列化,因为我不想在那里公开实现细节,所以 @JsonTypeInfo 不是不幸的是一个选项。
【问题讨论】:
标签: java json jackson jackson-databind