Холодної весняної ночі я нарешті перейшов на 33 рівень. Потираючи свої програмістські ручки, я вже готувався охопити всю сферу серіалізації, десеріалізації JSON, але, на жаль, нічого не зрозумів. Текст лекції не запам'ятався, а завдання вирішувалося якось інтуїтивно. У зв'язку з цим вирішив полізти в нетрі Jackson Framework і розібратися, що таке цей JSON.
Всі свої знання постараюся викласти практико-орієнтовано та лаконічно у форматі шпаргалки (як для себе, так і для читачів). Подорож у Jackson Annotations. Перше, що ми зустрічаємо на шляху до JSON – це інструкція @JsonAutoDetect. На перший погляд легка інструкція, але з нею автору довелося розбиратися найдовше. Інструкція має 5 необхідних нам способів:
- fieldVisibility () - серіалізує поля тільки із зазначеним модифікатором доступу
- getterVisibility()/setterVisibility() - серіалізує поля, у яких геттер/сеттер має вказаний модифікатор доступу
- isGetterVisibility() - окрема реалізація для булевських гетерів
@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;
}
}
А якщо прибрати це GetterVisibility? Чотири перераховані методи конфігурували процес серіалізації. П'ятий у свою чергу регулює процес десеріалізації:
- creatorVisibility() - найскладніший метод розуміння. Він працює з конструкторами та з фабричними методами (методи, які створюють об'єкт при зверненні до них). Розглянемо приклад:
@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);
}
Важливе зауваження щодо механізму десеріалізації! Коли ми намагаємося створити об'єкт із JSON, то буде здійснюватись пошук конструктора необхідного класу з таким же набором параметрів, що й у JSON об'єкті. У прикладі вище наш об'єкт JSON складається з двох параметрів: name, id. Вгадайте, якого конструктора він звернеться. І так, якщо ми скомпілюємо цей код, він випустить помилку, а чому? Тому що ми обмежабо видимість конструктора (видні тільки конструктори з модифікатором protected, public). Якщо ви видалите creatorVisibility, то він запрацює. Виникає питання. А що за @JsonProperty у конструкторі. Про це думаю розповісти у наступній частині статті. PSПанове, дуже хотілося б отримати хоч якийсь відгук про статтю. Цікаво, чи ця тема користується попитом і чи варто продовжувати, тому що тим дуже багато і всі вони дуже цікаві. Хотілося б розглянути такі анотації, як @JsonView, @JsonManagedReference, @JsonBackReference, @JsonUnwrapped і т.д. Дякую :)