JSON
JSON — текстовый формат обмена данными, основанный на синтаксисе JavaScript (но независим от языка). Типы: строки (в двойных кавычках), числа, boolean, null, массивы, объекты. Стандарт де-факто для REST API (легче и быстрее XML). Нет комментариев, дат (хранятся строками ISO 8601), ссылок. JSON Schema — описание структуры для валидации. Бинарные форматы (BSON, MessagePack) — компактнее, но нечитаемы (для высоконагруженных систем).
Введение: Язык, который понимают все
Представьте, что вы общаетесь с коллегой из другой страны. Вам нужен общий язык, который поймут оба. Не английский и не русский, а что-то простое, понятное и одинаковое для всех.
В мире обмена данными между программами таким языком стал JSON. Он не зависит от языка программирования: Python, Java, JavaScript, Go, C#, PHP — все понимают JSON.
JSON (JavaScript Object Notation) — это текстовый формат обмена данными, основанный на синтаксисе JavaScript объектов. Несмотря на название, он не имеет ничего общего с JavaScript, кроме внешнего вида. Это просто способ записывать структурированные данные в виде текста, понятного и человеку, и компьютеру.
JSON пришёл на смену XML, потому что он проще, легче и быстрее. Сегодня JSON — стандарт де-факто для REST API, конфигурационных файлов, обмена данными между сервером и браузером, хранения логов и многого другого. Почему? Потому что JSON легко читать, легко писать, легко парсить и он занимает мало места.
Почему JSON стал стандартом
До JSON доминировал XML. Он был мощным, но тяжеловесным.
XML (пример):
<person>
<name>Иван Петров</name>
<age>30</age>
<city>Москва</city>
<phones>
<phone>+7-999-123-45-67</phone>
<phone>+7-495-123-45-67</phone>
</phones>
</person>JSON (то же самое):
{
"name": "Иван Петров",
"age": 30,
"city": "Москва",
"phones": ["+7-999-123-45-67", "+7-495-123-45-67"]
}Почему JSON победил:
| Причина | Объяснение |
|---|---|
| Простота | JSON проще читать и писать |
| Лёгкость | JSON короче XML (нет закрывающих тегов) |
| Скорость | JSON парсится быстрее (не нужно парсить DOM) |
| Естественность | JSON маппится напрямую в структуры языков (словари, списки) |
| Наследие веба | JSON — это JavaScript, а веб — это JavaScript |
Основные типы данных JSON
JSON поддерживает всего несколько типов данных.
| Тип | Описание | Пример |
|---|---|---|
| Строка (string) | Текст в двойных кавычках | "Иван", "hello", "123" |
| Число (number) | Целое или дробное | 42, 3.14, -10, 1.5e3 |
| Логический (boolean) | Истина или ложь | true, false |
| Null | Пустое значение | null |
| Массив (array) | Упорядоченный список значений | [1, 2, 3], ["a", "b"] |
| Объект (object) | Набор пар “ключ-значение” | {"name": "Иван", "age": 30} |
Важно: Ключи в объектах всегда в двойных кавычках. Строки — всегда в двойных кавычках. Одинарные кавычки не допускаются стандартом (хотя некоторые парсеры их принимают).
Структура JSON
Объект (Object)
Объект — это неупорядоченный набор пар “ключ-значение”. Ключи — строки в двойных кавычках. Значения — любые типы JSON.
{
"name": "Иван",
"age": 30,
"is_active": true,
"address": {
"city": "Москва",
"street": "Тверская"
}
}Массив (Array)
Массив — упорядоченный список значений. Значения могут быть любого типа, в том числе разного.
["яблоко", "банан", "апельсин"]
[1, 2, 3, 4, 5]
[1, "два", true, null, {"name": "вложенный"}]
[
{"name": "Иван", "age": 30},
{"name": "Петр", "age": 25},
{"name": "Анна", "age": 35}
]Вложенность
JSON поддерживает любую глубину вложенности.
{
"company": "ТехноЛайн",
"departments": [
{
"name": "IT",
"employees": [
{"name": "Иван", "skills": ["Python", "SQL", "Docker"]},
{"name": "Петр", "skills": ["Java", "Kafka", "Kubernetes"]}
]
},
{
"name": "Sales",
"employees": [
{"name": "Анна", "skills": ["CRM", "Английский"]}
]
}
]
}Примеры JSON в реальной жизни
REST API ответ
{
"id": 123,
"name": "Иван Петров",
"email": "ivan@example.com",
"created_at": "2024-01-15T10:30:00Z",
"orders": [
{
"id": 1001,
"total": 5000,
"status": "delivered"
},
{
"id": 1002,
"total": 3000,
"status": "shipped"
}
]
}Конфигурационный файл
{
"app_name": "myapp",
"version": "1.2.3",
"debug": false,
"database": {
"host": "localhost",
"port": 5432,
"name": "mydb",
"user": "admin",
"password": "secret"
},
"features": ["analytics", "logging", "notifications"]
}Лог-файл (одна строка на событие)
{"timestamp": "2024-01-15T10:30:00Z", "level": "INFO", "message": "User logged in", "user_id": 123}
{"timestamp": "2024-01-15T10:31:00Z", "level": "ERROR", "message": "Database connection failed", "error": "timeout"}JSON в языках программирования
JavaScript
// Объект JavaScript (почти JSON, но ключи без кавычек)
const user = {
name: "Иван",
age: 30
};
// Преобразование в JSON (строку)
const jsonString = JSON.stringify(user);
// '{"name":"Иван","age":30}'
// Преобразование из JSON в объект
const parsedUser = JSON.parse(jsonString);
// { name: 'Иван', age: 30 }
Python
import json
# Словарь Python
user = {
"name": "Иван",
"age": 30
}
# Преобразование в JSON (строку)
json_string = json.dumps(user)
# '{"name": "\\u0418\\u0432\\u0430\\u043d", "age": 30}'
# С отступами (pretty print)
json_string = json.dumps(user, ensure_ascii=False, indent=2)
# Преобразование из JSON в словарь
parsed_user = json.loads(json_string)Java (Jackson)
import com.fasterxml.jackson.databind.ObjectMapper;
// Класс
public class User {
private String name;
private int age;
// getters, setters
}
// Сериализация
ObjectMapper mapper = new ObjectMapper();
User user = new User("Иван", 30);
String json = mapper.writeValueAsString(user);
// Десериализация
User parsed = mapper.readValue(json, User.class);Go
import "encoding/json"
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
user := User{Name: "Иван", Age: 30}
jsonBytes, _ := json.Marshal(user)
jsonString := string(jsonBytes)
var parsed User
json.Unmarshal(jsonBytes, &parsed)Валидный vs невалидный JSON
Валидный JSON
{
"name": "Иван",
"age": 30,
"is_active": true,
"tags": ["json", "api"],
"address": {
"city": "Москва",
"zip": 101000
},
"balance": null
}Невалидный JSON
// Ошибка 1: ключи без кавычек
{name: "Иван"}
// Ошибка 2: одинарные кавычки
{'name': 'Иван'}
// Ошибка 3: trailing comma
{"name": "Иван",}
// Ошибка 4: комментарии
{"name": "Иван"} // комментарий
// Ошибка 5: функции, undefined, NaN
{"name": undefined}Проверка валидности
| Инструмент | Как |
|---|---|
| jsonlint.com | Онлайн валидатор |
| jq | `echo ‘{“name”:“Иван”}’ |
| Python | json.loads(json_string) |
| VS Code | Подсветка синтаксиса |
Форматирование JSON
Минифицированный (minified)
{"name":"Иван","age":30,"address":{"city":"Москва","street":"Тверская"},"phones":["+7-999-123-45-67","+7-495-123-45-67"]}Когда использовать: Передача по сети (меньше трафика).
Pretty print (читаемый)
{
"name": "Иван",
"age": 30,
"address": {
"city": "Москва",
"street": "Тверская"
},
"phones": [
"+7-999-123-45-67",
"+7-495-123-45-67"
]
}Когда использовать: Конфигурационные файлы, отладка.
Проблемы и ограничения JSON
Нет комментариев
JSON не поддерживает комментарии. Это сделано намеренно (чтобы не усложнять парсеры).
Обходные пути:
// Плохо (невалидный JSON)
{
"name": "Иван", // это имя
"age": 30
}// Хорошо (валидный JSON)
{
"_comment": "Это имя пользователя",
"name": "Иван",
"_comment_age": "Возраст в годах",
"age": 30
}Нет дат и других специальных типов
JSON не имеет встроенного типа для даты, времени, десятичных чисел с фиксированной точкой.
Как хранят даты:
{
"created_at": "2024-01-15T10:30:00Z", // ISO 8601 строка
"date": "2024-01-15", // просто строка
"timestamp": 1705314600 // Unix timestamp (число)
}Нет ссылок
JSON не умеет ссылаться на другие части документа (как YAML или XML).
// Нельзя сделать ссылку
{
"default_address": {"city": "Москва", "street": "Тверская"},
"user_address": {REF: "default_address"} // нет такого
}Ограничение на размер
Формально нет лимита, но большинство парсеров имеют ограничения (обычно 100 МБ — 1 ГБ). Для больших файлов лучше использовать потоковые форматы.
JSON vs XML
| Характеристика | JSON | XML |
|---|---|---|
| Читаемость | Отличная | Средняя |
| Размер | Маленький | Большой |
| Скорость парсинга | Быстрая | Медленная |
| Поддержка типов | Базовая (строки, числа) | Все строки (нужна схема) |
| Комментарии | Нет | Да |
| Пространства имён | Нет | Да |
| Схема (validation) | JSON Schema (отдельно) | XML Schema, DTD |
| XPath / XQuery | Нет | Да |
| Популярность в API | 99% | <1% |
Вывод: JSON для веба, XML для документов и сложных схем.
JSON vs YAML
| Характеристика | JSON | YAML |
|---|---|---|
| Читаемость | Хорошая | Отличная |
| Комментарии | Нет | Да |
| Ссылки | Нет | Да |
| Сложность | Простой | Сложный (отступы) |
| Парсинг | Простой | Сложный |
| Конфиги | Хорошо | Отлично |
| API | Стандарт | Редко |
Вывод: JSON для API, YAML для конфигурационных файлов.
JSON Schema: Валидация JSON
JSON Schema — это язык описания структуры JSON. Позволяет валидировать, что JSON соответствует ожидаемой структуре.
Пример схемы
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"email": {
"type": "string",
"format": "email"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 0,
"maxItems": 10,
"uniqueItems": true
}
},
"required": ["name", "email"],
"additionalProperties": false
}Валидация
import jsonschema
schema = {...}
data = {"name": "Иван", "email": "ivan@example.com"}
try:
jsonschema.validate(data, schema)
print("JSON валиден")
except jsonschema.ValidationError as e:
print(f"Ошибка: {e.message}")Где используется: OpenAPI (Swagger), контракты API, тестирование.
Binary JSON (BSON, MessagePack, CBOR)
JSON текстовый, что удобно для человека, но неэффективно для машин.
| Формат | Тип | Размер | Скорость | Читаемость |
|---|---|---|---|---|
| JSON | Текст | 100% | 1x | Отличная |
| BSON (MongoDB) | Бинарный | ~80% | 1.2x | Нет |
| MessagePack | Бинарный | ~60% | 2x | Нет |
| CBOR | Бинарный | ~65% | 1.8x | Нет |
Когда использовать: Высокая нагрузка, большие объёмы данных, внутренние системы.
JSON Lines (JSONL)
Формат, где каждая строка — отдельный JSON объект.
{"id": 1, "name": "Иван"}
{"id": 2, "name": "Петр"}
{"id": 3, "name": "Анна"}Преимущества:
- Можно читать построчно (потоковая обработка)
- Легко добавлять в конец файла
- Подходит для логов, больших датасетов
Инструменты для работы с JSON
| Инструмент | Назначение |
|---|---|
| jsonlint.com | Валидация и форматирование |
| jsonpath.com | JSONPath запросы |
| jsonhero.io | Визуализация JSON |
| json2ts.com | JSON → TypeScript типы |
Распространённые ошибки
Ошибка 1: Одинарные кавычки
// Невалидно
{'name': 'Иван'}
// Валидно
{"name": "Иван"}Ошибка 2: Trailing comma
// Невалидно
{
"name": "Иван",
"age": 30,
}
// Валидно
{
"name": "Иван",
"age": 30
}Ошибка 3: Комментарии
// Невалидно
{
"name": "Иван", // это имя
"age": 30
}Ошибка 4: Неправильные числа
// Невалидно
{
"price": 12.50.00,
"count": 01
}
// Валидно
{
"price": 12.50,
"count": 1
}Ошибка 5: undefined, NaN, Infinity
// Невалидно
{
"value": undefined,
"not_a_number": NaN
}Резюме для системного аналитика
JSON — текстовый формат обмена данными. Простой, лёгкий, понятный. Стандарт для REST API, конфигов, логов.
Типы данных: строки (в двойных кавычках), числа, булевы, null, массивы, объекты. Нет дат, комментариев, ссылок.
JSON vs XML: JSON проще, легче, быстрее. XML мощнее (схемы, пространства имён, XPath). Для API — JSON. Для сложных документов — XML.
JSON vs YAML: YAML читаемее (комментарии, меньше кавычек), но сложнее. JSON для API, YAML для конфигов.
Валидность: ключи и строки в двойных кавычках, нет trailing comma, нет комментариев.
JSON Schema — язык описания структуры. Валидация, документация, генерация кода.
Бинарные форматы (BSON, MessagePack) — компактнее и быстрее, но нечитаемы. Для внутренних высоконагруженных систем.