Gymterview
junior

Что такое Jackson и как он работает?

Jackson — самая популярная библиотека для работы с JSON в Java-экосистеме. Центральный класс — ObjectMapper, который выполняет сериализацию (Java-объект -> JSON) и десериализацию (JSON -> Java-объект). Jackson используется по умолчанию в Spring Boot, Quarkus и Micronaut.

ObjectMapper: базовое использование

Пример конфигурации и сериализации/десериализации
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

public class JacksonBasicExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        // Конфигурация
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.registerModule(new JavaTimeModule());

        // Сериализация: объект -> JSON
        User user = new User("Иван", "ivan@example.com", 30);
        String json = mapper.writeValueAsString(user);
        // {"name":"Иван","email":"ivan@example.com","age":30}

        // Красивый вывод
        String prettyJson = mapper.writerWithDefaultPrettyPrinter()
                                  .writeValueAsString(user);

        // Десериализация: JSON -> объект
        String inputJson = """
            {"name":"Мария","email":"maria@example.com","age":25}
            """;
        User restored = mapper.readValue(inputJson, User.class);

        // Десериализация коллекций (generic-типы)
        String arrayJson = """
            [{"name":"Иван","age":30},{"name":"Мария","age":25}]
            """;
        List<User> users = mapper.readValue(arrayJson,
            new TypeReference<List<User>>() {});
    }
}

Основные аннотации

Аннотация Назначение Пример
@JsonProperty("name") Явное имя JSON-поля @JsonProperty("full_name")
@JsonIgnore Исключение поля На пароле, внутреннем коде
@JsonFormat Формат даты/числа @JsonFormat(pattern = "dd.MM.yyyy")
@JsonInclude Условие включения Include.NON_NULL — не писать null
@JsonAlias Альтернативные имена при чтении @JsonAlias({"email_address"})
@JsonNaming Стратегия именования на уровне класса SnakeCaseStrategy.class

Модуль JavaTimeModule

Обязателен для работы с java.time.* (LocalDate, LocalDateTime и др.). Без него Jackson выбросит InvalidDefinitionException.

Пример
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

Maven-зависимость:

Пример
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

Ключевые правила

  • ObjectMapper потокобезопасен после конфигурации — создавайте один экземпляр и переиспользуйте
  • FAIL_ON_UNKNOWN_PROPERTIES = false — критически важно для обратной совместимости API
  • TypeReference нужен для десериализации generic-типов, так как Java стирает generic-информацию в рантайме

Частые ошибки

  • Создание нового ObjectMapper на каждый запрос — потеря производительности
  • Забытый JavaTimeModule при использовании LocalDate/LocalDateTime
  • Отсутствие конструктора без аргументов — Jackson не сможет создать объект (если не использовать @JsonCreator)
  • FAIL_ON_UNKNOWN_PROPERTIES = true (по умолчанию) — падение при добавлении новых полей в API

На собеседовании: покажите знание ObjectMapper, назовите 3-4 основные аннотации и упомяните JavaTimeModule. Частая проверка — знаете ли вы, что ObjectMapper нужно переиспользовать, а не создавать каждый раз.