Введение в JSON на Java
Обзор основных JSON-библиотек для Java: Jackson, Gson, JSON-B и org.json.
JSON (JavaScript Object Notation) — наиболее распространённый формат обмена данными в вебе. API возвращают его, конфигурационные файлы используют его, а сервисы передают его друг другу. В ядре JDK нет встроенной поддержки JSON, поэтому работа с ним означает выбор библиотеки — но концепции разбора, маппинга и сериализации одинаковы, какую бы вы ни выбрали.
Эта страница является картой раздела JSON: она объясняет, что такое JSON, как его типы соотносятся с типами Java, какие существуют библиотеки и две модели разбора. Последующие главы детально рассматривают две наиболее популярные библиотеки — JSON с Jackson и JSON с Gson.
Что такое JSON
JSON — это лёгкий текстовый формат для структурированных данных. Он построен из нескольких простых типов: строки, числа, булевы значения, null, массивы (упорядоченные списки) и объекты (отображения ключ/значение). Поскольку это обычный текст, любой язык может его читать и записывать — именно поэтому JSON стал общим языком веб-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 object -> JSON text (serialize)
String json = mapper.writeValueAsString(user);
// JSON text -> Java object (deserialize)
User parsed = mapper.readValue(json, User.class);Gson следует той же схеме с другими именами:
import com.google.gson.Gson;
Gson gson = new Gson();
String json = gson.toJson(user); // serialize
User parsed = gson.fromJson(json, User.class); // deserializeДобавьте библиотеку как зависимость перед использованием — для Jackson это com.fasterxml.jackson.core:jackson-databind; для Gson — com.google.code.gson:gson.
Какую выбрать? Если вы используете Spring Boot, Jackson уже там и настроен — используйте его. Для небольшого автономного инструмента или Android-приложения, где важен размер бинарника, удобен крошечный, не требующий настройки API Gson. Обращайтесь к JSON-B только когда вы привязаны к стеку Jakarta EE и хотите vendor-neutral стандарт. На практике выбор редко влияет на корректность — все три читают и записывают одинаковый JSON — поэтому предпочтите тот, который уже есть у вас в classpath.
Два способа разбора: дерево и привязка
Какую бы библиотеку вы ни выбрали, существуют две основные модели чтения JSON:
- Привязка данных (Data binding) отображает JSON непосредственно на Java-классы. Вы определяете класс (или record), поля которого совпадают с ключами, и библиотека его заполняет. Это наиболее чистый подход, когда структура известна и стабильна.
- Модель дерева/карты разбирает JSON в обобщённое дерево узлов (
JsonNodeв Jackson) илиMap<String, Object>. Вы навигируете по ключу. Используйте этот подход, когда структура динамична или вам нужно лишь несколько полей.
// Binding: structure known ahead of time
record User(String name, int age, boolean admin) {}
User u = mapper.readValue(json, User.class);
System.out.println(u.name());
// Tree: navigate without a class
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сохраняет порядок вставки, поэтому сериализованные ключи появляются в порядке, в котором они были добавлены — это полезно для стабильного, удобного для сравнения вывода.