W zimną wiosenną noc w końcu osiągnąłem poziom 33. Zacierając ręce programisty, przygotowywałem się już do ogarnięcia całego zakresu serializacji i deserializacji JSON, ale niestety nic nie rozumiałem. Nie pamiętałem tekstu wykładu, ale problemy rozwiązano jakoś intuicyjnie. W związku z tym postanowiłem zagłębić się w dzicz Jackson Framework i dowiedzieć się, czym jest ten JSON.
Całą moją wiedzę postaram się przedstawić w sposób praktyczny i zwięzły w formie ściągawki (zarówno dla siebie, jak i dla czytelników). Adnotacje Podróż do Jacksona. Pierwszą rzeczą, którą spotykamy w drodze do JSON, jest adnotacja @JsonAutoDetect. Na pierwszy rzut oka jest to proste podsumowanie, jednak autorowi zajęło najwięcej czasu jego rozszyfrowanie. Streszczenie ma 5 metod, których potrzebujemy:
- FieldVisibility () — Serializuje tylko pola z określonym modyfikatorem dostępu
- getterVisibility()/setterVisibility() - serializuje pola, których getter/setter ma określony modyfikator dostępu
- isGetterVisibility() - osobna implementacja dla modułów pobierających wartość boolowską
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY,
getterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY,
setterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY,
isGetterVisibility = JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC)
public class HeadClass {
public String name;
private Map<String, String> properties;
public Queue<String> queue;
protected List<String> list;
private int age;
private int number;
private boolean isHead;
protected HeadClass(int age) {
this.age = age;
}
public HeadClass() {}
Map<String, String> getProperties() {
return properties;
}
protected boolean isHead() {
return isHead;
}
protected void setProperties(Map<String, String> properties) {
this.properties = properties;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
Co się stanie, jeśli usuniemy isGetterVisibility? Cztery wymienione metody konfigurowały proces serializacji. Piąty z kolei reguluje proces deserializacji:
- createVisibility() to metoda najtrudniejsza do zrozumienia. Działa z konstruktorami i metodami fabrycznymi (metodami, które po wywołaniu tworzą obiekt). Spójrzmy na przykład:
@JsonAutoDetect(creatorVisibility = JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC)
public class HeadClass {
public String name;
public int id;
HeadClass(@JsonProperty(value = "name") String name, @JsonProperty(value = "id") int id) {
this.name = name;
this.id = id;
}
protected HeadClass(String name) {
this.name = name;
this.id = 123;
}
protected HeadClass(int id) {
this.id = id;
this.name = "Yes!";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
String forDeserialize = "{\"name\":\"No!\",\"id\":123}";
StringReader reader = new StringReader(forDeserialize);
HeadClass headClass1 = (HeadClass) mapper.readValue(reader, HeadClass.class);
}
Ważna uwaga na temat mechanizmu deserializacji! Gdy spróbujemy utworzyć obiekt z JSON, konstruktor wymaganej klasy zostanie przeszukany z takim samym zestawem parametrów jak w obiekcie JSON. W powyższym przykładzie nasz obiekt JSON składa się z dwóch parametrów: name, id. Zgadnij, jakiego konstruktora wywoła. I tak, jeśli skompilujemy ten kod, wyświetli się błąd, dlaczego? Ponieważ ograniczyliśmy widoczność konstruktora (widoczne są tylko konstruktory z chronionym, publicznym modyfikatorem). Jeśli usuniesz CreatorVisibility, zadziała. Nasuwa się pytanie. Co to jest @JsonProperty w konstruktorze? Myślę, że o tym opowiem w dalszej części artykułu. PS Panowie bardzo chciałbym uzyskać chociaż jakąś odpowiedź na temat artykułu. Zastanawiam się, czy jest na ten temat zapotrzebowanie i czy warto go kontynuować, bo tematów jest mnóstwo i wszystkie są bardzo ciekawe. Chciałbym również rozważyć adnotacje takie jak @JsonView, @JsonManagedReference, @JsonBackReference, @JsonUnwrapped itp. Dziękuję :)
GO TO FULL VERSION