2009-08-24 1 views
10

В следующем коде Джексон/Java, который сериализует объекты в JSON, я получаю это:Использование Джексона ObjectMapper сериализовать имя подкласса в JSON, не суперкласса

{"animal":{"x":"x"}} 

Однако то, что я на самом деле хочу, чтобы получить это:

{"dog":{"x":"x"}} 

есть ли что-то я могу сделать, чтобы AnimalContainer так, что я получаю тип выполнения («собака», «кошка») объекта, а не «животное»)? (Редактировать: Мне известно, что имя карты происходит от имени метода getter и setter.) Единственный способ, которым я могу это сделать, - это в AnimalContainer иметь атрибут каждого типа Animal, иметь сеттеров и геттеров для всех из них, и обеспечить, чтобы только один оценивался за раз. Но это побеждает цель иметь Суперкласс животных и просто кажется неправильным. И в моем реальном коде у меня на самом деле есть дюжина подклассов, а не только «собака» и «кошка». Есть ли лучший способ сделать это (возможно, используя аннотации)? Мне также нужно решение для десериализации.

public class Test 
{ 
    public static void main(String[] args) throws Exception 
    { 
     AnimalContainer animalContainer = new AnimalContainer(); 
     animalContainer.setAnimal(new Dog()); 

     StringWriter sw = new StringWriter(); // serialize 
     ObjectMapper mapper = new ObjectMapper(); 
     MappingJsonFactory jsonFactory = new MappingJsonFactory(); 
     JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw); 
     mapper.writeValue(jsonGenerator, animalContainer); 
     sw.close(); 
     System.out.println(sw.getBuffer().toString()); 
    } 
    public static class AnimalContainer 
    { 
     private Animal animal; 
     public Animal getAnimal() {return animal;} 
     public void setAnimal(Animal animal) {this.animal = animal;} 
    } 
    public abstract static class Animal 
    { 
     String x = "x"; 
     public String getX() {return x;} 
    } 
    public static class Dog extends Animal {} 
    public static class Cat extends Animal {} 
} 

ответ

9

В соответствии с this announement, Jackson 1.5 реализует полную обработку полиморфного типа, а соединительная линия теперь имеет этот код.

Есть два простых способа, чтобы сделать эту работу:

  • Добавить @JsonTypeInfo аннотацию в надтипа (Animal здесь) или
  • Настройка объекта картографа по телефону ObjectMapper.enableDefaultTyping() (но если это так, Animal должен быть абстрактным типом)
+1

есть ли способ решить с помощью ObjectMapper.enableDefaultTyping() 'без необходимости абстрактного Animal? Я использую Jackson 1.9, и я пробовал это, но все еще не работает ..... –

+0

По умолчанию типизация может использовать разные критерии, см. Javadocs, включая пользовательское определение того, к чему это следует применить. – StaxMan

0

Это единственный способ, которым я могу это сделать, и это уродливо. Есть ли способ лучше?

@JsonWriteNullProperties(false) 
    public static class AnimalContainer 
    { 
     private Animal animal; 

     public Animal getCat() 
     { 
     return animal instanceof Cat ? animal : null; 
     } 
     public void setCat(Cat cat) 
     { 
     this.animal = cat; 
     } 
     public Animal getDog() 
     { 
     return animal instanceof Dog ? animal : null; 
     } 
     public void setDog(Dog dog) 
     { 
     this.animal = dog; 
     } 
     public Animal getFish() 
     { 
     return animal instanceof Fish ? animal : null; 
     } 
     public void setFish(Fish fish) 
     { 
     this.animal = fish; 
     } 
    } 
2

Это, вероятно, не ответ, который вы ищете, но есть планы по осуществлению надлежащих «полиморфные десериализаций» (и необходимая поддержка на сериализации для него), для Джексона версии 1.4 или так (т.е. не следующий один, 1,3, но один после этого).

Для текущей версии вы должны реализовать пользовательские сериализаторы/десериализаторы: я бы, вероятно, просто определил заводский метод десериализации и тип getter для сериализатора (определите 'getAnimalType' или что-то в абстрактном базовом классе как абстрактное, классы - или даже просто реализовать в базовом классе, имя выходного класса класса экземпляра?).

Во всяком случае, только в случае, если это имеет значение, здесь основные проблемы WRT, реализующий обработку подклассов с JSON и без языка схемы (так как JSON не очень широко используется один):

  • как для разделения данных (значения свойств компонента) из метаданных (информация о типе, необходимая только для создания соответствующих подклассов) - должна храниться отдельно, но формат JSON в формате не имеет возможности определить (может использовать соглашение об именах)
  • как добавить соответствующие аннотации создавать и использовать такие метаданные; и не зависит от специфических особенностей языка (например, не нужно привязываться к именам классов java)

Это разрешимые проблемы, но их нетрудно решить. :-)

+0

По крайней мере, это подтверждение того, что в Джексоне нет возможности сделать это, но я ничего не пропущу; это должно быть сделано трудным путем. – seansand

+0

Правильно. Я не могу придумать способ сделать это легко (без специального сериализатора/десериализатора) с помощью Jackson 1.2 или раньше. – StaxMan

+0

FWIW, версия Jackson 1.5 будет поддерживать полную обработку полиморфизма для десериализации (только что был выпущен 1.4). – StaxMan

Смежные вопросы