Введение в 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 |
|---|---|
| object | Map<String, Object> или POJO/record |
| array | List<?> или T[] |
| string | String |
| number | int, long, double, BigDecimal |
true / false | boolean / Boolean |
null | null |
Почему 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 библиотеки, который вы будете использовать в проекте.
Что вынести из запуска:
- Разобранный объект 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?