📚 EVEDAYS Guide Book
[Инструменты разработчика]•6 мин чтения

Пять причин, почему JSON не парсится, и ловушка больших чисел

1. JSON строже, чем кажется


JSON похож на литерал объекта JavaScript, но допускает гораздо меньше. Он определён в RFC 8259 и ECMA-404, и многое из того, что допустимо в JavaScript, в JSON недопустимо.

2. Пять причин ошибки парсинга


① Висячая запятая
{"a": 1, "b": 2,} — запятая после последнего элемента — ошибка. JavaScript её допускает, JSON — нет.

② Ключи без кавычек
{a: 1} — ключи должны быть строками в двойных кавычках.

③ Одинарные кавычки
{'a': 'b'} — JSON признаёт только двойные кавычки.

④ Комментарии
Ни // заметка, ни /* */ в стандартном JSON не существуют. Конфигурационным файлам, которым нужны комментарии, следует использовать расширения вроде JSONC или JSON5.

⑤ Специальные значения
NaN, Infinity и undefined — не JSON. Отсутствующее число записывайте как null или строкой.

Ещё одна частая ошибка — настоящий перевод строки внутри строки; его нужно экранировать как \n.

3. Как читать позицию ошибки


Парсеры обычно сообщают что-то вроде «position 42», но настоящая причина часто находится раньше. Из-за одной пропущенной кавычки парсер поглощает остаток документа как часть строки и падает намного дальше.

Если пропустить документ через форматтер и развернуть структуру, несовпадающую вложенность легко заметить.

4. Ловушка больших чисел


Это не синтаксическая ошибка, а незаметное изменение значения, поэтому она опаснее.

Числа в JavaScript — это числа с плавающей точкой двойной точности, поэтому целые числа представляются точно только до:

Number.MAX_SAFE_INTEGER = 9007199254740991

При разборе большего целого через JSON.parse его значение незаметно меняется. Например, 12345678901234567890 превращается в 12345678901234567000 — без ошибки и без предупреждения.

Когда это бьёт по вам
  • 64-битные ID в стиле Snowflake (Twitter, Discord и подобные)

  • Первичные ключи BIGINT из базы данных

  • Крупные денежные суммы в минимальных единицах


  • Решение
    Стандартный способ — чтобы сервер сериализовал такие значения как строки: {"id": "12345678901234567890"}. Если клиенту нужно работать с ними как с числами, используйте BigInt со своей функцией reviver.

    5. Разновидности JSON


    | Формат | Отличие | Где используется |
    |---|---|---|
    | JSON | Стандарт | Ответы API, обмен данными |
    | JSONC | Допускает комментарии | Настройки VS Code и подобные |
    | JSON5 | Комментарии, висячие запятые, одинарные кавычки | Конфигурационные файлы, написанные вручную |
    | NDJSON / JSON Lines | Одно значение JSON на строку | Логи, потоковая передача, пакетная обработка |

    Не отдавайте JSONC из API только потому, что он работает в конфигурационном файле: стандартные парсеры его отклонят.

    6. Замечание о безопасности


    До сих пор иногда встречается код, который пропускает строку JSON через eval(). Никогда так не делайте. Недоверенные входные данные, содержащие код, будут выполнены как код. JSON.parse безопасен.

    7. Инструмент


    Форматтер JSON EVEDAYS проверяет и форматирует JSON прямо в браузере. Ответы API часто содержат персональные данные или токены, поэтому инструмент, который никуда их не передаёт, — более безопасный выбор.

    8. Источники


  • RFC 8259 — The JavaScript Object Notation (JSON) Data Interchange Format

  • ECMA-404 — The JSON Data Interchange Syntax

  • MDN — JSON.parse()
  • EVEDAYS Editorial Team