2017-08-01 64 views
5

Co @JsonTypeInfo i @JsonSubTypes adnotacje używając w Jackson?Co @JsonTypeInfo i @JsonSubTypes stosowane w Jackson

public class Lion extends Animal { 

private String name; 

@JsonCreator 
public Lion(@JsonProperty("name") String name) { 
    this.name = name; 
} 

public String getName() { 
    return name; 
} 

public String getSound() { 
    return "Roar"; 
} 

public String getType() { 
    return "carnivorous"; 
} 

public boolean isEndangered() { 
    return true; 
} 

@Override 
public String toString() { 
    return "Lion [name=" + name + ", getName()=" + getName() + ", getSound()=" + getSound() + ", getType()=" + getType() + ", isEndangered()=" 
      + isEndangered() + "]"; 
} 

} 

========================================

public class Elephant extends Animal { 

@JsonProperty 
private String name; 

@JsonCreator 
public Elephant(@JsonProperty("name") String name) { 
    this.name = name; 
} 

public String getName() { 
    return name; 
} 

public String getSound() { 
    return "trumpet"; 
} 

public String getType() { 
    return "herbivorous"; 
} 

public boolean isEndangered() { 
    return false; 
} 

@Override 
public String toString() { 
    return "Elephant [name=" + name + ", getName()=" + getName() + ", getSound()=" + getSound() + ", getType()=" + getType() 
      + ", isEndangered()=" + isEndangered() + "]"; 
} 
} 

==============================================

@JsonTypeInfo (use = JsonTypeInfo.Id.CLASS, include = As.PROPERTY, property = "classNameExtenral") 
@JsonSubTypes ({@Type (value = Lion.class, name = "lion"), @Type (value = Elephant.class, name = "elephant")}) 

public abstract class Animal { 

@JsonProperty ("name") 
String name; 
@JsonProperty ("sound") 
String sound; 
@JsonProperty ("type") 
String type; 
@JsonProperty ("endangered") 
boolean endangered; 
} 

public static void main(String[] args){ 
    Lion lion = new Lion("Simba"); 
    Elephant elephant = new Elephant("Manny"); 
    List<Animal> animals = new ArrayList<>(); 
    animals.add(lion); 
    animals.add(elephant); 
} 

Co rozumiem jest że dodatkowo chroni konkretny typ obiektu szeregowane wraz z danymi rzeczywistymi.

Co nie jest dla mnie jasne to jaka jest rzeczywista przewaga/zysk podczas deserializacji.

Nie otrzymuję żadnej znaczącej dokumentacji poza dokumentami java. Czy ktokolwiek może ci pomóc1 lub dostarczyć trochę dokumentów na ten temat.

+0

Może ta odpowiedź pomoże: https://stackoverflow.com/a/31666888/751579 – davidbak

+0

Pomaga .. dzięki. – Harshit

Odpowiedz

6

Celem tych adnotacji jest wspieranie polimorfizmu w przypadku deserializacji. Podczas deserializacji rzeczywistego wykonywanego kodu będzie znać klasa tego, czego oczekuje. Np. Typ pola przekształcanego w postaci szeregowej. Ale jeśli ta klasa ma podklasy (tj. Podtypy), w jaki sposób ogólny deserializator Jackson wie, która klasa faktycznie jest deserializacją łańcucha? Musi utworzyć instancję jakiegoś konkretnego typu (klasy lub jednej z jej podklas) i uzupełnić ją. Jedynym sposobem, aby dowiedzieć się, który z nich utworzyć, jest umieszczenie tej informacji w pierwszej kolejności.

Jak this answer mówi, że są trzy sposoby, aby to zrobić - wybrać taki, który jest odpowiedni dla Twojego przypadku użycia. @JsonTypeInfo + @JsonSubtypes to jeden z tych sposobów - działa świetnie, gdy wiesz, w czasie kompilacji, wszystkie możliwe podtypy, które mogą istnieć dla danej klasy.

+0

Czy używanie @JsonTypeInfo na poszczególnych klasach konkretnych nie ma większego sensu? Używanie go w interfejsie wydaje się naruszać zasadę otwartego zamknięcia (jak w przypadku, gdy potrzebujemy zmodyfikować nasz interfejs przy każdym nowym dodaniu konkretnej implementacji). Proszę mnie poprawić, jeśli czegoś tu nie ma – Harshit

+0

Ponownie, zależy to od przypadku użycia. Na przykład miałem przypadek użycia, w którym mogłem w rzeczywistości używać @JsonSubtypes w jednym miejscu, a to było lepsze niż tagowanie każdego podtypu. Ale TBH zapomniałem, jaki był teraz ten przypadek użycia; Przypominam sobie, że to było trochę niezwykłe. Ale miało to więcej wspólnego z praktycznymi problemami związanymi z wdrożeniem/wydaniem niż czysta teoria OO. (Pamiętaj: dowolna "zasada", taka jak open-close, jest tylko silną wytyczną ... w niektórych przypadkach możesz stwierdzić, że naruszenie takiej zasady jest prawidłowe - po prostu upewnij się, że naprawdę wiesz dlaczego.) – davidbak

+1

Zastanów się, czy masz klasę Cage który zawiera pole typu Animal. Kiedy obiekt Cage jest deserializowany z JSON, Jackson odkrywa, że ​​powinien stworzyć Zwierzę, więc jeśli Zwierzę nie zostanie opatrzone adnotacją @JsonTypeInfo, Jackson nie zastosuje wsparcia dla polimorfizmu, więc stworzy tylko Zwierzę (jeśli to możliwe) i nie jest jego podtypem. –