Перейти к содержимому

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”:“Иван”}’
Pythonjson.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

ХарактеристикаJSONXML
ЧитаемостьОтличнаяСредняя
РазмерМаленькийБольшой
Скорость парсингаБыстраяМедленная
Поддержка типовБазовая (строки, числа)Все строки (нужна схема)
КомментарииНетДа
Пространства имёнНетДа
Схема (validation)JSON Schema (отдельно)XML Schema, DTD
XPath / XQueryНетДа
Популярность в API99%<1%

Вывод: JSON для веба, XML для документов и сложных схем.

JSON vs YAML

ХарактеристикаJSONYAML
ЧитаемостьХорошаяОтличная
КомментарииНетДа
СсылкиНетДа
СложностьПростойСложный (отступы)
ПарсингПростойСложный
КонфигиХорошоОтлично
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.comJSONPath запросы
jsonhero.ioВизуализация JSON
json2ts.comJSON → 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
}

Резюме для системного аналитика

  1. JSON — текстовый формат обмена данными. Простой, лёгкий, понятный. Стандарт для REST API, конфигов, логов.

  2. Типы данных: строки (в двойных кавычках), числа, булевы, null, массивы, объекты. Нет дат, комментариев, ссылок.

  3. JSON vs XML: JSON проще, легче, быстрее. XML мощнее (схемы, пространства имён, XPath). Для API — JSON. Для сложных документов — XML.

  4. JSON vs YAML: YAML читаемее (комментарии, меньше кавычек), но сложнее. JSON для API, YAML для конфигов.

  5. Валидность: ключи и строки в двойных кавычках, нет trailing comma, нет комментариев.

  6. JSON Schema — язык описания структуры. Валидация, документация, генерация кода.

  7. Бинарные форматы (BSON, MessagePack) — компактнее и быстрее, но нечитаемы. Для внутренних высоконагруженных систем.

Проверка знаний

Вопрос 1 из 4
Почему JSON стал стандартом де-факто для REST API?
Какое правило синтаксиса JSON является обязательным?
Какого встроенного типа данных в JSON нет?
Для чего используется JSON Schema?

Вопросы, где были ошибки