Пользователь Mikhail Fufaev
Mikhail Fufaev
35 уровень
Москва

Введение в Jackson Framework

Статья из группы Random
Холодной весенней ночью я наконец-таки перешел на 33 уровень. Потирая свои программистские ручки, я уже готовился объять всю сферу сериализации, десериализации JSON, но, к сожалению, ничего не понял. Текст лекции не запомнился, а задачи решались как-то интуитивно. В связи с этим решил полезть в дебри Jackson Framework и разобраться, что же такое этот JSON.
Jackson Framework
Все свои познания постараюсь изложить практико-ориентированно и лаконично в формате шпаргалки (как для себя, так и для читателей). Путешествие в Jackson Annotations. Первое, что мы встречаем на пути в JSON — это аннотация @JsonAutoDetect. На первый взгляд легкая аннотация, но с ней автору пришлось разбираться дольше всего. Аннотация имеет 5 нужных нам методов:
  • fieldVisibility() - сериализует поля только с указанным модификатором доступа
  • getterVisibility()/setterVisibility() - сериализует поля, у которых геттер/сеттер имеет указанный модификатор доступа
  • isGetterVisibility() - отдельная реализация для булевских геттеров
Важно понимать, что методы работают дизъюнктивно. Т.е. если поле соответствует хотя бы одному из указанных в аннотации параметров, то оно попадет в JSON. Попытайтесь ответить, что выведет данный код, если мы создадим экземляр, используя конструктор без параметров:

@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;
    }
}
А если убрать isGetterVisibility? Четыре перечисленных метода конфигурировали процесс сериализации. Пятый же в свою очередь регулирует процесс десериализации:
  • 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 в конструкторе. Об этом думаю рассказать в следующей части статьи. P.S. Господа, очень бы хотелось получить хоть какой-то отклик о статье. Интересно, пользуется ли спросом эта тема и стоит ли продолжать, потому что тем очень много и все они очень интересные. Хотелось бы еще рассмотреть такие аннотации, как @JsonView, @JsonManagedReference, @JsonBackReference, @JsonUnwrapped и т.д. Спасибо :)
Комментарии (13)
Чтобы просмотреть все комментарии или оставить свой,
перейдите в полную версию
Soros 39 уровень, Харьков
1 апреля 2020
Видимо было очень холодно, что спустя два года продолжения нет.
Egor Patrikeev 22 уровень, Ashkelon
24 августа 2019
Доходчиво и по сути!! Спасибо очень помог, 2 часа бился пока не надыбал эту статью!
Александр Кулага 1 уровень, Харьков
21 июля 2019
Очень полезно и интересно - будем благодарны за продолжение.
Jors 1 уровень, Санкт-Петербург
21 июня 2019
А мне понравилось объяснение которое я посмотрел на ютюбе Изучение Jackson
Роман И 20 уровень
26 апреля 2019
Да, вот возникла потребность разобраться. Надо было сохранить переименованное поле для совместимости со старыми версиями клиентов.
Арман Матаков 39 уровень, Алматы
4 апреля 2019
Было бы здорово если бы было еще, но как то более развернуто, с пояснениями, что куда и как работает.
rmuskovets 41 уровень, Ровно
7 ноября 2018
помогло мне, а то забыл всё
Ярослав 40 уровень, Днепр Master
15 июня 2018
Спасибо за статью, поставили кое-какие вещи на свои места в моей голове :)
Сергей 40 уровень, Москва Expert
24 мая 2018
Не статья, а огрызок какой-то
Евгений Гродно 36 уровень Expert
1 мая 2018
Довольно интересный способ подачи, хочу вам рассказать, но вы догадайтесь. Может лучше взять отдельную аннотацию, и раскрыть Ее возможности, показать пример, как будет выглядеть код без аннотации. Вы учитывайте, что есть часть аудитории, кто ещё и до 10 уровня не дошёл, а вы тут так ругаетесь. ;)