Предоставить Джексону экземпляр пользовательского объекта без TypeInfo - PullRequest
1 голос
/ 24 апреля 2019

Я пытаюсь десериализовать некоторые полиморфные объекты, используя Джексона, но я не хочу раскрывать информацию о типе в JSON.Итак, допустим, у нас есть «классический» сценарий Animals:

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. Я знаю только два варианта:

  • Использование @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 экземпляр, но затем позволил Джексону применить магию привязки данных вместо того, чтобы все это реализовывать вручную?Для справки: в случае, если у кого-то есть опыт работы с JAXB, что-то вроде @XmlRegistry, где я могу указать фабрику для данного интерфейса, было бы здорово.

Спасибо!

РЕДАКТИРОВАТЬ: это былоВозможно, это и так понятно, но я не хочу помещать свойство type в JSON для десериализации, потому что я не хочу раскрывать там детали реализации, поэтому, к сожалению, @JsonTypeInfo не вариант.

1 Ответ

0 голосов
/ 24 апреля 2019

Вы можете использовать @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();
}
...