В комментариях к моим прошлым статьям («Усложнённый упрощённый JSON» и «JSON для любителей скобочек») неоднократно прозвучали вопросы о смысле, сложности, удобности и применимости этого формата. Итак, спешу поздравить всех неравнодушных — Вы дождались!
Содержание
Введение
Задача №1. Представление документов на иерархических структрах данных
Задача №2. Реализация драйвера
О формате NSNJSON
Заключение
^ Введение
Всё началось с моего знакомства с одной интересной NoSQL СУБД, а именно, InterSystems Cache. Компания InterSystems ведет блог на Хабрахабре, в котором можно почитать о внутреннем устройстве этой СУБД. Скажу лишь, что ESA использует InterSystems Cache в проекте GAIA (спасибо за поправку tsafin и morrison).
Для того, чтобы понять дальнейшую суть необходимо знать, что данные в Cache хранятся в глобалах (можно думать о глобале, как о иерархической структуре данных). Более подробно о глобалах можно почитать в следующих статьях:
- GlobalsDB — универсальная NoSQL база данных. Часть 1,
- GlobalsDB — универсальная NoSQL база данных. Часть 2.
В рамках моей магистерской программы, был начат проект по реализации документо-ориентированной NoSQL на основе Cache. Теоретической исследовательской базой этого проекта является концептуальный вопрос о быстродействии, производительности и надежности такой реализации, по сравнению с существующим решением. В качестве опорной документо-ориентированной NoSQL была выбрана моя любимая MongoDB.
Итак, что же я имел в своем начале пути?
1. Документо-ориентированную NoSQL MongoDB.
2. Иерархическую NoSQL Cache.
^ Задача №1. Представление документов на иерархических структрах данных
Казалось бы, JSON документы итак можно назвать иерархическими, и потому никакой сложности в этой задаче нет. Однако,
Напомню, что JSON формат определяет 6 типов: null, number, string, true, false, array, object. Таким образом, требовалось придумать однозначную схему представления данных для каждого JSON типа, имя в распоряжении лишь возможность строить иерархии и использовать, в качестве значений для листов дерева, строки и числа. Однако, к схеме представления JSON данных выдвигалось еще одно требование — однозначность. Это условие — гарант однозначной восстанавливаемости JSON данных из глобалов.
Немного поясню этот момент.
Рассмотрим JSON тип null. Можно было бы предложить для него простую схему. Допустим, если есть значения типа JSON null, то при сохранении этого значения в глобал необходимо создать лист и установить в качестве значения пустую строку "". Однако, первый же контрпример приходит очень быстро, — схема теряет однозначность в тот момент, когда нам потребуется сохранить значение типа JSON string, равное пустой строке. В связи с этим я решил перейти на другую, довольно простую схему.
JSON number (значение value)
Например, для значения value
2015
представление было бы следующим:JSON string (значение value)
Например, для значения value
"R&D"
представление было бы следующим:JSON true
JSON false
JSON array
Например, для массива
[ 2015, "R&D" ]
представление было бы следующим:JSON object
Например, для объекта
{ "year": 2015, "section": "R&D" }
представление было бы следующим:
Можно считать, что эта схема и стала прародителем формата NSNJSON.
Теперь, когда схема представления JSON данных готова, меня ждал следующий шаг на моем пути. Мне нужно было разработать драйвер для этой документо-ориентированной NoSQL СУБД.
^ Задача №2. Реализация драйвера
Реализация драйвера состоит из двух этапов:
- разработка хранимого кода (в Cache, на языке Cache ObjectScript),
- разработка кода, который будет обращаться к драйверу Cache и передавать данные хранимому коду.
Для передачи данных между моим драйвером и драйвером Cache, я выбрал простой формат, — строковый. Мой драйвер получал JSON, преобразовывал в строку и передавал драйверу Cache, тот в свою очередь передавал эту строку хранимому коду. Хранимый код парсил эту строку, а далее применял правила представления JSON данных на глобалах.
Однако, меня ждал сюрприз!
Во время разработки и отладки выяснилось несколько интересных фактов об используемом мной JSON парсере в хранимом коде Cache:
- JSON тип null транслируется в "",
- JSON тип true транслируется в 1,
- JSON тип false транслируется в 0.
- поля начинающиеся со знака _ игнорируются.
Таким образом, мне нужно было решить следующие проблемы:
- сохранение информации о типе,
- сохранение полей, начинающихся со знака _.
Решением этих проблем стал разработанный мной формат NSNJSON.
Так, для значений типа null предлагалось следующее представление:
{ "t": "null" }
Для значений типа true предлагалось следующее представление:
{ "t": "boolean", "v": 1 }
Для значений типа false предлагалось следующее представление:
{ "t": "boolean", "v": 0 }
Проблема с _ решилась с помощью введения поля «n».
Так, для поля _id со значением 213, представление было бы таким:
{ "n": "_id", "t": "number", "v": 213 }
Таким образом, данный формат решил все ранее указанные проблемы.
^ О формате NSNJSON
Я решил выделить формат в отдельный проект и назвать NSNJSON (Not So Normal JSON). А потом я решил поделиться этим фоматом с уважаемым сообществом Хабрахабра в своей статье «Усложнённый упрощённый JSON», а также, об интересной, на мой взгляд, модификации этого формата, в котором JSON данные представляются с помощью чисел, строк и массивов, в статье «JSON для любителей скобочек».
Проект NSNJSON опубликован на GitHub.
Для него реализованы два драйвера:
^ Заключение
Вот и подошла к концу заключительная статья о NSNJSON. Я рассказал о трудностях с которыми столкнулся, а также о том, как я их преодолел.
На последок, хочу еще раз отметить, что это был мой ? (путь), и я его прошёл именно таким образом. На каждом шаге можно было бы пойти по-другому, выбирая другой вариант решения возникавших проблем, но это был бы уже не мой путь…
Комментарии (15)
NeoCode
06.11.2015 09:07В JSON все что не хватает — это комментариев.
Я бы предложил такое:
Однострочные //
Многострочные /* */
И блочные (для структурного комментирования скобочного блока) #mayorovp
06.11.2015 22:21+1Блочный комментарий сделает JSON несовместимым с JS…
Eternalko
10.11.2015 07:24-1Для красоты и удобства могу присоветовать CSON. Coffescript JSON.
Тот же JSON только в Coffee. Плюс в том что нет запятых и скобочек и все красиво.
И вместо `require('config.json')` даем `require('config.cson')` и все.
Очень удобно.mayorovp
10.11.2015 08:57Да-да, очень. Особенно тем, кто никогда не писал require('config.json') :)
Eternalko
10.11.2015 18:58-1Писать в JS и не писать `require` немного странно )
mayorovp
10.11.2015 19:09Я не говорил, что не писал require (хотя в этом тоже нет ничего странного, всего лишь ручная сборка зависимостей). Я сказал, что никогда не загружал конфиг через require…
Для справки: js — это не только сервер-сайд в виде node.js, некоторые люди еще и скрипты для браузера пишут :)
morisson
06.11.2015 12:49Скажу лишь, что NASA использует InterSystems Cache в проекте GAIA.
Поправочка: не NASA, а ESA.
vintage
Раз уж это магистерская, то имело бы смысл реализовывать не примитивную документоориентированную субд, а хотя бы графовую. Ну и опять же, не понятно зачем ограничиваться именно JSON, если он для этой задачи не слишком подходит.