JSON: Формат и кодирование
JSON — обзор
JSON (JavaScript Object Notation) — текстовый формат обмена данными, стандартизированный в RFC 8259 (2017). Создан Дугласом Крокфордом на основе подмножества JavaScript-синтаксиса. Де-факто стандарт для REST API, конфигурационных файлов, и обмена данными между микросервисами.
В отличие от CSV, JSON имеет систему типов и поддерживает вложенные структуры. Но за читаемость и гибкость приходится платить — encoding overhead JSON выше, чем у бинарных форматов, в 3-10 раз.
Модель данных: 6 типов
RFC 8259 определяет ровно 6 типов значений:
JSON не различает целые и вещественные числа. 42 и 42.0 — оба number. Это означает, что JSON не может гарантировать сохранение типа: записали int64 42, прочитали float64 42.0. Для финансовых данных (где 0.1 + 0.2 ≠ 0.3 в float) это критично — Avro Decimal или Protobuf fixed-point лучше.
Encoding overhead: байт-за-байтом
JSON-кодирование избыточно: ключи повторяются в каждом объекте, числа хранятся как текст, скобки и кавычки добавляют постоянный overhead:
Но главный overhead — повторение ключей:
Числовая точность: IEEE 754 double
JSON number — это текстовое представление числа. RFC 8259 не ограничивает точность, но большинство парсеров (JavaScript, Python json, Go encoding/json) преобразуют числа в IEEE 754 double (64-bit):
Twitter (X) API возвращает id (number) и id_str (string) для каждого твита именно из-за этой проблемы. JavaScript JSON.parse() преобразует id в IEEE 754 double, теряя последние цифры 64-bit Snowflake ID. Всегда используйте id_str для идентификаторов, или библиотеки с BigInt-поддержкой (Python: json.loads() использует arbitrary-precision int, проблемы нет).
JSON Lines (NDJSON): потоковая обработка
Обычный JSON — массив объектов [{...}, {...}, ...] — не подходит для потоковой обработки: парсер должен прочитать весь массив, чтобы разобрать структуру. JSON Lines (он же NDJSON — Newline-Delimited JSON) решает эту проблему:
JSON Lines splittable by design: JSON escape для newline — \n (два символа: backslash + n), а настоящий newline (0x0A) внутри JSON string невозможен. Поэтому каждый \n в файле — гарантированно разделитель записей. В отличие от CSV, где \n внутри quoted field — часть значения.
JSON в data pipelines
JSON повсеместен в data engineering, но с разными ролями на каждом этапе:
JSON Schema: валидация без типов
JSON Schema (draft 2020-12) — отдельный стандарт для описания и валидации структуры JSON-документов. Не является частью RFC 8259, но широко используется для API-контрактов:
JSON Schema — валидация, не кодирование. В отличие от Avro Schema (определяет wire format) и Protobuf .proto (генерирует код), JSON Schema только проверяет структуру готового JSON. Документ всё равно кодируется как текст со всем overhead. JSON Schema используется в OpenAPI (Swagger), API Gateway validation, и CI/CD для контрактных тестов.
Размер данных: JSON vs бинарные форматы
Итог
JSON — хороший формат транспорта: читаемый, самоописывающий, поддерживается везде. Плохой формат хранения: encoding overhead 3-10x, отсутствие числовой точности, repeated keys. В data pipelines JSON живёт на входе (API, landing zone) и должен конвертироваться в бинарный/columnar формат как можно раньше. JSON Lines — предпочтительная форма для потоковой обработки и логирования.