W3docs

Введение в Java JSON

Обзор основных библиотек JSON, доступных для Java — Jackson, Gson, JSON-B и org.json.

Введение в Java JSON

JSON (JavaScript Object Notation) — самый распространённый формат для обмена данными в вебе. API возвращают его, файлы конфигурации используют его, а сервисы передают его друг другу. В Java нет встроенной в ядро JDK поддержки JSON, поэтому работа с JSON означает выбор библиотеки — но концепции разбора, отображения и сериализации остаются одними и теми же, какую бы вы ни выбрали.

Что такое JSON

JSON — это лёгкий текстовый формат для структурированных данных. Он построен из нескольких простых типов: строки, числа, булевы значения, null, массивы (упорядоченные списки) и объекты (отображения ключ/значение). Поскольку это обычный текст, любой язык может его читать и записывать, и именно поэтому он стал лингва-франка веб-API.

{
  "name": "Ann",
  "age": 30,
  "admin": true,
  "roles": ["editor", "author"],
  "address": null
}

Формат чисто отображается на типы языков программирования. В Java объект JSON становится Map или собственным классом, массив становится List или массивом, а скалярные типы становятся String, Number, Boolean и null.

Тип JSONЭквивалент в Java
objectMap<String, Object> или POJO/record
arrayList<?> или T[]
stringString
numberint, long, double, BigDecimal
true / falseboolean / Boolean
nullnull

Почему JSON важен

JSON — это полезная нагрузка по умолчанию для REST-API, и программы Java постоянно отправляют и принимают его: веб-сервис читает тело JSON-запроса, запрашивает базу данных и записывает JSON-ответ. Он также человекочитаем, поэтому одновременно служит форматом конфигурации и логирования.

По сравнению с XML — более старым форматом обмена, который JSON в значительной мере вытеснил — JSON лаконичнее, имеет меньше церемоний и отображается более прямо на структуры данных языков. XML по-прежнему выигрывает там, где вам нужны схемы, пространства имён или смешанное содержимое, но для простого обмена данными JSON обычно более лёгкий выбор.

Основные библиотеки Java

JDK не поставляет парсер JSON, поэтому вы добавляете его. Доминируют три библиотеки:

БиблиотекаСильная сторонаТипичное применение
JacksonБыстрая, богатая возможностями, потоковая + связываниеДе-факто стандарт; встроена в Spring Boot
GsonПростой API, малый размерAndroid, быстрые скрипты
JSON-P / JSON-B (Jakarta)Официальный стандарт Jakarta EEКорпоративные/Jakarta-приложения

Jackson используется наиболее широко. Её центральный класс — ObjectMapper, который преобразует между текстом JSON и объектами Java одним вызовом:

import com.fasterxml.jackson.databind.ObjectMapper;

ObjectMapper mapper = new ObjectMapper();

// Объект Java -> текст JSON (сериализация)
String json = mapper.writeValueAsString(user);

// Текст JSON -> объект Java (десериализация)
User parsed = mapper.readValue(json, User.class);

Gson следует той же форме с другими именами:

import com.google.gson.Gson;

Gson gson = new Gson();
String json = gson.toJson(user);          // сериализация
User parsed = gson.fromJson(json, User.class); // десериализация

Добавьте библиотеку как зависимость, прежде чем использовать её — для Jackson это com.fasterxml.jackson.core:jackson-databind; для Gson — com.google.code.gson:gson.

Два способа разбора: дерево против связывания

Какую бы библиотеку вы ни выбрали, есть две основные модели чтения JSON:

  • Связывание данных (data binding) отображает JSON прямо на классы Java. Вы определяете класс (или record), поля которого соответствуют ключам, и библиотека заполняет его. Это самый чистый подход, когда структура известна и стабильна.
  • Модель дерева/map разбирает JSON в обобщённое дерево узлов (JsonNode в Jackson) или Map<String, Object>. Вы навигируете по ключу. Используйте её, когда форма динамична или вам нужно лишь несколько полей.
// Связывание: структура известна заранее
record User(String name, int age, boolean admin) {}
User u = mapper.readValue(json, User.class);
System.out.println(u.name());

// Дерево: навигация без класса
JsonNode root = mapper.readTree(json);
System.out.println(root.get("name").asText());

Связывание даёт вам безопасность типов и читаемый код; модель дерева даёт вам гибкость. Большинство приложений используют связывание для собственных доменных объектов и обращаются к модели дерева только для слабо структурированных данных.

Запускаемый пример

В песочнице нет ни Jackson, ни Gson в classpath, поэтому программа ниже использует только коллекции JDK, чтобы продемонстрировать ту же идею: разобранный объект JSON — это просто ключи, отображённые на типизированные значения, массив — это List, а сериализация превращает эту структуру обратно в текст JSON. Статические примеры выше показывают настоящий API библиотеки, который вы будете использовать в проекте.

java— editable, runs on the server

Что вынести из запуска:

  • Разобранный объект JSON ведёт себя как Map: вы получаете каждое поле по его ключу, точно так же, как mapper.readTree(...).get("name") в Jackson.
  • Значения JSON сохраняют свой тип — age возвращается как Number, а admin — как Boolean, а не как сырой текст, поэтому age instanceof Number печатает true.
  • Массив JSON отображается на List, поэтому roles итерируем и сообщает размер 2.
  • Сериализация — это обратная сторона разбора: обход той же структуры заново собирает компактный текст JSON {"name":"Ann",...}.
  • Использование LinkedHashMap сохраняет порядок вставки, поэтому сериализованные ключи появляются в том порядке, в котором они были добавлены — полезно для стабильного, удобного для diff вывода.

Практика

Практика

На что наиболее естественно отображается массив JSON в Java?