在没有TypeInfo的情况下向Jackson提供自定义对象实例

时间:2019-04-24 13:57:57

标签: java json jackson jackson-databind

我正在尝试使用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中使用@JsonTypeInfotype参数来污染实现细节的JSON,所以我只知道两种选择:

  • @JsonDeserialize(as = Dog.class)上使用Animal,但这将需要从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实例的方法,然后让Jackson进行数据绑定魔术而不是手动实现所有方法?作为参考,如果有人对JAXB有一定的经验,那么像@XmlRegistry这样的地方,我可以为给定的接口指定工厂,真是太棒了。

谢谢!

编辑:可能还不清楚,但是我不想在JSON中放置一个type属性以进行反序列化,因为我不想在那里公开实现细节,所以{{1 }}不幸的是不是一个选择。

1 个答案:

答案 0 :(得分:0)

您可以使用@JsonTypeInfo@JsonSubtypes来自动支持多态。

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Cat.class, name = "cat"),
    @JsonSubTypes.Type(value = Dog.class, name = "dog")
})

public interface Animal {
    String talk();
}