Рубрики
Без рубрики

Лунатик: JSON без аннотации

Jackson – это мощная библиотека для обработки JSON. Это библиотека по умолчанию, используемая рамкой Spring… С тегами java, json, джексон, показать разработчика.

Jackson – это мощная библиотека для обработки JSON. Это библиотека по умолчанию, используемая платформой Spring. Он очень гибкий и настраиваемый. Стандартный способ его настройки – использование аннотаций в обрабатываемых классах.

В этом посте я объясню, как использовать библиотеку Moonwalker , которую я создал. Это фасад для Джексона и предоставляет API-интерфейс разработчика для настройки Джексона. Таким образом, вы можете избавиться от аннотаций в своих классах. Я также покажу вам, как интегрировать Moonwalker в приложения Spring Boot.

Прежде чем мы погрузимся в примеры кода, почему вы хотите избавиться от аннотаций в своих классах? Причин может быть несколько, в том числе:

  • Аннотации относятся к JSON, и вы не хотите привязывать себя к использованию JSON в качестве механизма сериализации.
  • У вас нет доступа к некоторым классам, в которые вам нужно было бы поместить аннотации, например, суперклассы фреймворка.
  • Вы следуете принципам проектирования, управляемого доменом (DDD), чтобы публиковать/подписываться на события домена, и не хотите, чтобы ваши классы событий домена были загромождены аннотациями, специфичными для технологии.

Давайте рассмотрим варианты использования и то, как Moonwalker может помочь в этом.

Допустим, у вас есть суперкласс Человек , с подклассом Сотрудник . Стандартный способ рассказать Джексону об отношениях наследования – использовать аннотации в суперклассе:

@JsonTypeInfo(property = "@type", include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.MINIMAL_CLASS)
@JsonSubTypes({ @JsonSubTypes.Type(value = Employee.class) })
public class Person {

  private String firstName;
  private String lastName;

  public Person() {
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
}

Что означает свойство в аннотации? Он объявляет, что JSON содержит свойство с именем @type . Его значением является имя подкласса, чтобы Джексон знал, какой конкретный экземпляр класса создавать при десериализации. Как вы можете видеть, суперкласс должен содержать все подклассы, в данном случае класс Employee . Вот код:

public class Employee extends Person{
  private String employeeNumber;

  public Employee() {
  }

  public String getEmployeeNumber() {
    return employeeNumber;
  }

  public void setEmployeeNumber(String employeeNumber) {
    this.employeeNumber = employeeNumber;
  }
}

Вот как вы десериализуете JSON в объект Employee , учитывая, что класс Employee находится в том же пакете, что и класс Person .

ObjectMapper objectMapper = new ObjectMapper();
String jsonString = "{ \"@type\" : \".Employee\", \"firstName\" : \"Jane\", \"lastName\" : \"Doe\" , \"employeeNumber\" : \"EMP-2020\"}";
Employee employee = (Employee) objectMapper.readValue(jsonString, Person.class);

Как Лунатик справляется с наследованием

Когда вы используете Moonwalker, вы можете избавиться от всех аннотаций в суперклассе. Вместо этого вы создаете и регистрируете модуль, содержащий сопоставление между свойством JSON, например @тип и суперкласс, например Человек :

ObjectMapper objectMapper = new ObjectMapper();

MoonwlkerModule module =
  MoonwlkerModule.builder()
    .fromProperty("@type").toSubclassesOf(Person.class)
    .build();

objectMapper.registerModule(module);

JSON выглядит почти идентично, за исключением того, что перед именем класса в свойстве @type нет начальной точки:

String jsonString = "{ \"@type\" : \"Employee\", \"firstName\" : \"Jane\", \"lastName\" : \"Doe\" , \"employeeNumber\" : \"EMP-2020\"}";
Employee employee = (Employee) objectMapper.readValue(jsonString, Person.class);

И это все.

Чтобы интегрировать Moonwalker в проект Spring Boot, все, что вам нужно сделать, это зарегистрировать компонент для ObjectMapper :

@SpringBootApplication
public class GreeterApplication {
  public static void main(String[] args) {
    SpringApplication.run(GreeterApplication.class, args);
  }

  @Bean
  ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();

    MoonwlkerModule module =
      MoonwlkerModule.builder()
        .fromProperty("@type").toSubclassesOf(Person.class)
        .build();

    objectMapper.registerModule(module);
    return objectMapper;
  } 
}

Стандартным способом, которым Джексон поддерживает все конструкторы аргументов, является использование @JsonCreator и @jsonproperties аннотации. Moonwalker изменяет это: он позволяет десериализовать объекты, у которых есть один конструктор по умолчанию для всех аргументов.

Пример класса, который может быть (де)сериализован с помощью Moonwalker, может выглядеть следующим образом:

public class Dog extends Animal {
  private final String name;
  private final String command;

  public Dog(BigDecimal price, String name, String command) {
    super(price);
    this.name = name;
    this.command = command;
  }

  public String name() {
    return name;
  }

  public String command() {
    return command;
  }
}

Подробнее о том, как включить эту функцию, смотрите на веб-сайте Moonwalker .

Проект “Лунный ходок” находится в стадии разработки. Любая обратная связь приветствуется. Оставьте заметку в комментариях. Или станьте участником. Спасибо!

Оригинал: “https://dev.to/bertilmuth/moonwlker-json-without-annotation-1692”