Персональный сайт Олега Барабанова

Основные недостатки JSON

Итак, в настоящее время JSON является очень популярным форматом хранения данных, конфигов, а также удобен как формат передачи текстовых данных. Не в последнюю очередь он стал популярен благодаря стремительному развитию web-технологий и JavaScript в частности.

В данной статье я хотел бы немного обсудить недостатки JSON и затронуть тему JSON5.

О преимуществах JSON написано огромное количество информации, поэтому просто перечислю основные на мой взгляд: простота, немногословность, четкая структура и соответственно широкая популярность. В JSON нет огромного количества правил, пространств имен как в XML и соответственно парсинг этого формата выполняется очень быстро (в сравнении с тем же XML).

Пример сравнения, который показывает, насколько немногословен JSON в сравнении с XML:

// Example XML:
<?xml version="1.1" encoding="UTF-8" ?>
<userlist>
  <user name="Иван" surname="Иванов" />
  <user name="Петр" surname="Петров" />
  <user name="Сидор" surname="Сидоров" />
</userlist>
// Example JSON:
[
  { name: "Иван", surname: "Иванов" },
  { name: "Петр", surname: "Петров" },
  { name: "Сидор", surname: "Сидоров" }
]

Но тем не менее забегу наперед и скажу, что JSON не является полноценной заменой XML и вытеснил его только там, где не нужна вся мощь стандартов XML.

Естественно у JSON есть не только положительные, но и отрицательные стороны, знание которых поможет вам соориентироваться, где стоит применять JSON, а где нет.

Проблема 1. Отсутствие нормальных комментариев в JSON

На мой взгляд, одним из существенных недостатков этого формата, является отсутствие нормальной поддержки комментариев. Когда данные гоняются в виде JSON при RPC или REST, в этом нет необходимости, но вот когда JSON используется в форматах конфигов - это уже проблема. Когда смотришь в проекте очередной огромный package.json или config.json, то глаза на лоб лезут от отсутствия пояснений по каким-то неочевидным моментам. 

Часто хочется просто оставить маленький комментарий в стиле в стиле того же JS:

...
"rules": {
  "vue/max-attributes-per-line": "off", //disabled because it is not compatible with "Prettier"
}
...

Но в JSON это будет ошибкой. Решением такой проблемы является добавление какого-то свойства, четко обозначающего комментарий:

...
"rules": {
  "__comment__vue/max-attributes-per-line": "disabled because it is not compatible with \"Prettier\"",
  "vue/max-attributes-per-line": "off",
}
...

Т.е. мы фактически добавляем новое значение и должны иметь какое-то соглашение, т.к. по логике мы ожидаем в rules одно правило, а по факту получаем 2. Т.е. там, где обрабатывается JSON, должна стоять последующая фильтрация значений, начинающихся с "__comment__".

Вместо __comment__ можно задать любой признак комментария, какой вам удобен. Даже для такого случая нет какого-то общепринятого наименования таких "комментариев". Да и в общем такие комментарии достаточно уродливы и могут доставить больше проблем чем пользы.

Проблема 2. Хранение бинарных данных в JSON

В силу того, что JSON является текстовым форматом, бинарные данные в нем безопасно не получится. Точно таким же недостатком обладает и XML.

Для решения этой проблемы применяют Base64 кодирование, результат которого можно безопасно использовать в JSON. Но к такому решению надо подходить с осторожностью, т.к. имеются добавление файлов, кодированных base64 имеет следующие последствия:

Стоит рассмотреть возможность вместо непосредственной вставки бинарных данных в JSON, указывать в виде строки ссылку или URI к источнику, с которого можно выгрузить файл.

Проблема 3. Отсутствие BigInteger

О проблеме точности больших чисел (IEEE 754) я уже упоминал в статье "Проблемы больших чисел в JavaScript или зачем нужен тип BigInt".

Вкратце, если в вашем JSON например есть число 23845061135960375, то при парсинге вы скорее всего получите значение 23845061135960376, что может вас достаточно удивить.

Решением этой проблемы является передача больших чисел в виде строки.

JSON5

Попыткой решить часть проблем JSON можно назвать JSON5, который его разработчики называют как "JSON for humans".

По факту, он является интересной идеей (и реализацией!), решения некоторых проблем JSON как формата, причем с полностью сформулированной спецификацией, которая совместима с JSON и просто расширяет его. Т.е. любой JSON является валидным для JSON5, но не любой JSON5 является валидным согласно JSON.

К сожалению JSON5 не является каким-то широко используемым стандартом и маловероятно что скоро будет, но в отдельных проектах, для тех же настроек его вполне можно использовать.

Итог

Как итог, я скажу, что недостатки JSON вполне широко известны и просто хочу  напомнить о том, что формат хранения и передачи данных нужно выбирать исходя из задачи, а не исходя из принципа "везде использовали и сюда засунем". Просто важно понимать, что небывает идеального формата для всех случаев.