Работа с JSON в C++: парсинг и сериализация
JSON (JavaScript Object Notation) остаётся одним из самых популярных форматов для обмена данными в веб-приложениях, конфигурационных файлах и API. Несмотря на то, что C++ не имеет встроенной поддержки JSON, существует несколько мощных библиотек, которые делают работу с этим форматом простой и эффективной. В этой статье мы рассмотрим две самые популярные библиотеки: nlohmann/json (рекомендуется для большинства проектов) и RapidJSON (для задач, где критична производительность). Вы узнаете, как парсить JSON, сериализовать объекты обратно в строку и обрабатывать ошибки.
Зачем нужен JSON в C++?
C++ — язык системного программирования, но современные приложения всё чаще требуют взаимодействия с веб-сервисами, хранения конфигураций или обмена данными между микросервисами. JSON предоставляет удобный, человекочитаемый формат для этих задач. Использование библиотек для работы с JSON в C++ позволяет:
- Загружать и обрабатывать конфигурационные файлы (например, для игровых движков или серверов).
- Взаимодействовать с REST API (отправка и получение данных).
- Сохранять и восстанавливать состояние сложных структур данных.
- Интегрироваться с другими языками и системами, использующими JSON.
Библиотека nlohmann/json: простота и удобство
Библиотека nlohmann/json (часто называемая "JSON for Modern C++") является, пожалуй, самой популярной благодаря своему интуитивному API, напоминающему работу с Python или JavaScript. Она поддерживает C++11 и выше.
Установка
Самый простой способ — скопировать единственный заголовочный файл json.hpp в ваш проект. Вы можете скачать его с официального репозитория или установить через пакетный менеджер (vcpkg, Conan).
Парсинг JSON из строки
Рассмотрим базовый пример парсинга строки JSON и доступа к данным:
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main() {
// Строка JSON для парсинга
std::string json_string = R"({
"name": "С++",
"version": 17,
"features": ["RAII", "Templates", "Smart Pointers"],
"is_compiled": true
})";
// Парсинг строки в объект json
json data = json::parse(json_string);
// Доступ к значениям
std::cout << "Язык: " << data["name"] << std::endl;
std::cout << "Версия: " << data["version"] << std::endl;
std::cout << "Компилируемый: " << data["is_compiled"] << std::endl;
// Доступ к массиву
for (auto& feature : data["features"]) {
std::cout << " - " << feature << std::endl;
}
return 0;
}
Вывод:
Язык: "С++"
Версия: 17
Компилируемый: true
- "RAII"
- "Templates"
- "Smart Pointers"
Сериализация (создание JSON)
Создать JSON объект и преобразовать его в строку так же просто:
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main() {
// Создаем объект JSON
json person;
person["name"] = "Alice";
person["age"] = 30;
person["is_student"] = false;
person["hobbies"] = {"reading", "coding", "chess"};
// Добавляем вложенный объект
person["address"]["city"] = "Moscow";
person["address"]["zip"] = "101000";
// Сериализация в строку с отступами
std::string serialized = person.dump(4); // 4 пробела для отступа
std::cout << serialized << std::endl;
return 0;
}
Метод dump(4) возвращает красиво отформатированную строку. Для компактного вывода используйте dump() без аргументов.
Обработка ошибок парсинга
При работе с внешними данными важно обрабатывать исключения:
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main() {
std::string invalid_json = R"({ "key": "value" )"; // Пропущена закрывающая скобка
try {
json data = json::parse(invalid_json);
} catch (json::parse_error& e) {
std::cerr << "Ошибка парсинга JSON: " << e.what() << std::endl;
std::cerr << "Позиция ошибки: " << e.byte << std::endl;
}
return 0;
}
Библиотека RapidJSON: производительность и гибкость
RapidJSON — это библиотека, разработанная с фокусом на максимальную скорость и минимальное потребление памяти. Она идеально подходит для высоконагруженных систем, где важна каждая микросекунда. RapidJSON написан на C++11 и является header-only (только заголовочные файлы).
Установка
Скачайте файлы из репозитория RapidJSON и включите директорию include в пути вашего проекта.
Парсинг с помощью RapidJSON
RapidJSON использует DOM-подход, но с более низкоуровневым управлением памятью:
#include <iostream>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
int main() {
const char* json = "{\"project\":\"RapidJSON\",\"version\":1.1,\"stars\":15000}";
rapidjson::Document doc;
doc.Parse(json);
// Проверка на ошибки парсинга
if (doc.HasParseError()) {
std::cerr << "Ошибка парсинга: " <&