Что такое JSON
JSON (JavaScript Object Notation) — это текстовый формат обмена данными, удобный одновременно для чтения человеком и для обработки машиной. Несмотря на происхождение из JavaScript, формат давно стал языконезависимым стандартом и используется практически везде, где приложениям нужно обмениваться структурированными данными.
Базовый пример JSON-документа:
{
"id": 42,
"name": "Анна",
"is_active": true,
"roles": ["admin", "editor"],
"profile": {
"city": "Тбилиси",
"age": 29
}
}
Формат строится из нескольких простых типов: объекты (пары «ключ — значение»), массивы, строки, числа, логические значения и null. Эта простота и стала причиной его повсеместного распространения.
Что такое парсинг JSON и зачем он нужен
Парсинг JSON (разбор) — это процесс преобразования JSON-текста в структуру данных, понятную конкретному языку программирования: объект, словарь, массив, список и т. д. По сути парсер берёт строку символов и превращает её в живые объекты, с которыми можно работать в коде.
Обратный процесс — превращение объектов программы обратно в JSON-строку — называется сериализацией (или маршалингом). Парсинг и сериализация почти всегда идут парой.
Парсинг нужен в типичных задачах:
- Работа с API — получение и отправка данных по HTTP (об этом подробнее ниже).
- Конфигурационные файлы — многие инструменты хранят настройки в JSON (
package.json,tsconfig.jsonи др.). - Хранение и обмен данными — логи, сообщения в очередях (Kafka, RabbitMQ), документы в NoSQL-базах (MongoDB).
- Межсервисное взаимодействие в микросервисной архитектуре.
- Сохранение состояния приложения в файлы или localStorage в браузере.
Парсинг JSON при работе с API
Самый частый сценарий, в котором разработчик сталкивается с парсингом JSON, — это взаимодействие с API. Подавляющее большинство современных веб-API (REST, а нередко и другие стили) обмениваются данными именно в формате JSON.
Типичный цикл работы с API выглядит так:
- Клиент отправляет HTTP-запрос на эндпоинт API.
- Сервер отвечает телом ответа в виде JSON-строки.
- Клиент парсит эту строку, превращая её в объекты, и работает с данными дальше.
- При отправке данных (POST, PUT) клиент, наоборот, сериализует свои объекты в JSON.
Без шага парсинга ответ сервера остаётся просто текстом, с которым нельзя удобно работать программно. Поэтому парсинг — обязательное звено почти в любой интеграции с внешним сервисом.
См. также: материал «Парсинг API» — там подробно разбирается, как устроены запросы к API, как обрабатывать ответы, работать с заголовками, статус-кодами, пагинацией и аутентификацией. Настоящая статья сосредоточена именно на этапе разбора самих JSON-данных, который является составной частью этого процесса.
Примеры реализации парсинга JSON на разных языках
Ниже приведены примеры разбора JSON в популярных языках. В каждом случае разбирается одна и та же строка, а затем извлекается значение вложенного поля.
Python
В стандартной библиотеке есть модуль json. Метод loads разбирает строку, load — содержимое файла.
import json
data_str = '{"name": "Анна", "profile": {"city": "Тбилиси", "age": 29}}'
# Парсинг строки в словарь
data = json.loads(data_str)
print(data["name"]) # Анна
print(data["profile"]["city"]) # Тбилиси
# Обратная операция — сериализация
back_to_str = json.dumps(data, ensure_ascii=False)
JavaScript
В JavaScript парсинг встроен в язык через глобальный объект JSON. Это и есть «родной» формат экосистемы.
const dataStr = '{"name": "Анна", "profile": {"city": "Тбилиси", "age": 29}}';
// Парсинг строки в объект
const data = JSON.parse(dataStr);
console.log(data.name); // Анна
console.log(data.profile.city); // Тбилиси
// Обратная операция
const backToStr = JSON.stringify(data);
При работе с fetch парсинг ответа API делается одной строкой:
const response = await fetch("https://api.example.com/users/42");
const user = await response.json(); // ответ уже распарсен в объект
console.log(user.name);
Java
В стандартной библиотеке нет встроенного парсера, поэтому обычно используют библиотеки — например, Jackson или Gson. Пример с Jackson:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws Exception {
String dataStr = "{\"name\": \"Анна\", \"profile\": {\"city\": \"Тбилиси\"}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(dataStr);
System.out.println(node.get("name").asText()); // Анна
System.out.println(node.get("profile").get("city").asText()); // Тбилиси
}
}
Чаще JSON разбирают сразу в типизированный класс (POJO):
record Profile(String city, int age) {}
record User(String name, Profile profile) {}
User user = mapper.readValue(dataStr, User.class);
System.out.println(user.profile().city());
Go
В стандартной библиотеке есть пакет encoding/json. Данные обычно разбирают в структуру с тегами полей.
package main
import (
"encoding/json"
"fmt"
)
type Profile struct {
City string `json:"city"`
Age int `json:"age"`
}
type User struct {
Name string `json:"name"`
Profile Profile `json:"profile"`
}
func main() {
dataStr := `{"name": "Анна", "profile": {"city": "Тбилиси", "age": 29}}`
var user User
json.Unmarshal([]byte(dataStr), &user)
fmt.Println(user.Name) // Анна
fmt.Println(user.Profile.City) // Тбилиси
}
C
В современном .NET есть встроенное пространство имён System.Text.Json.
using System;
using System.Text.Json;
class Program
{
static void Main()
{
string dataStr = "{\"name\": \"Анна\", \"profile\": {\"city\": \"Тбилиси\"}}";
using JsonDocument doc = JsonDocument.Parse(dataStr);
JsonElement root = doc.RootElement;
Console.WriteLine(root.GetProperty("name").GetString()); // Анна
Console.WriteLine(root.GetProperty("profile").GetProperty("city").GetString()); // Тбилиси
}
}
PHP
В PHP парсинг встроен в язык через функции json_decode и json_encode.
<?php
$dataStr = '{"name": "Анна", "profile": {"city": "Тбилиси", "age": 29}}';
// true — разбирать в ассоциативный массив, а не в объект
$data = json_decode($dataStr, true);
echo $data["name"]; // Анна
echo $data["profile"]["city"]; // Тбилиси
// Обратная операция
$backToStr = json_encode($data, JSON_UNESCAPED_UNICODE);
Rust
В экосистеме Rust де-факто стандартом является крейт serde вместе с serde_json.
use serde::Deserialize;
#[derive(Deserialize)]
struct Profile {
city: String,
age: u32,
}
#[derive(Deserialize)]
struct User {
name: String,
profile: Profile,
}
fn main() {
let data_str = r#"{"name": "Анна", "profile": {"city": "Тбилиси", "age": 29}}"#;
let user: User = serde_json::from_str(data_str).unwrap();
println!("{}", user.name); // Анна
println!("{}", user.profile.city); // Тбилиси
}
Сравнение подходов
| Язык | Инструмент | Встроен в язык |
|---|---|---|
| Python | json |
Да |
| JavaScript | JSON |
Да |
| Java | Jackson / Gson | Нет |
| Go | encoding/json |
Да |
| C# | System.Text.Json |
Да |
| PHP | json_decode |
Да |
| Rust | serde / serde_json | Нет |
Заметно два основных подхода к разбору:
- Динамический разбор — JSON превращается в универсальную структуру (словарь, массив, дерево узлов). Удобно для быстрой и гибкой работы, но без проверки типов на этапе компиляции.
- Типизированный разбор — JSON сразу отображается в заранее описанные классы или структуры. Безопаснее и нагляднее, особенно в строго типизированных языках (Java, Go, Rust, C#).
Частые проблемы и рекомендации
При парсинге JSON стоит учитывать несколько типичных сложностей:
- Невалидный JSON. Если строка повреждена или содержит синтаксические ошибки, парсер выбросит исключение. Разбор внешних данных всегда стоит оборачивать в обработку ошибок.
- Отсутствующие или
null-поля. Не предполагайте, что все ожидаемые ключи всегда присутствуют, — API может прислать неполный объект. Проверяйте наличие полей перед обращением. - Кодировка. JSON по стандарту использует UTF-8. В некоторых языках (Python, PHP) нужно явно указывать флаги, чтобы кириллица не превращалась в
\u-последовательности при сериализации. - Большие документы. Для очень больших файлов вместо загрузки всего объекта в память применяют потоковый (streaming) разбор, читающий данные по частям.
- Числа и точность. Большие целые числа и числа с плавающей точкой могут терять точность — для финансовых данных это критично, и их иногда передают строками.
Итог
Парсинг JSON — это базовый навык, без которого почти невозможна работа с современными API и обмен данными между системами. Сам формат универсален, а инструменты для его разбора есть в каждом распространённом языке программирования: где-то встроенные, где-то в виде популярных библиотек. Принцип везде одинаков — превратить текстовую строку в удобные для кода объекты, а при необходимости проделать обратный путь.
Чтобы увидеть, как парсинг встраивается в полный цикл взаимодействия с внешними сервисами, обратитесь к материалу «Парсинг API».