? — путь. В этой заключительной статье о формате NSNJSON я хочу рассказать о моем пути, который привел меня к изобретению этого формата.

В комментариях к моим прошлым статьям («Усложнённый упрощённый JSON» и «JSON для любителей скобочек») неоднократно прозвучали вопросы о смысле, сложности, удобности и применимости этого формата. Итак, спешу поздравить всех неравнодушных — Вы дождались!




Содержание


    Введение
    Задача №1. Представление документов на иерархических структрах данных
    Задача №2. Реализация драйвера
    О формате NSNJSON
    Заключение

^ Введение


Всё началось с моего знакомства с одной интересной NoSQL СУБД, а именно, InterSystems Cache. Компания InterSystems ведет блог на Хабрахабре, в котором можно почитать о внутреннем устройстве этой СУБД. Скажу лишь, что ESA использует InterSystems Cache в проекте GAIA (спасибо за поправку tsafin и morrison).

Для того, чтобы понять дальнейшую суть необходимо знать, что данные в Cache хранятся в глобалах (можно думать о глобале, как о иерархической структуре данных). Более подробно о глобалах можно почитать в следующих статьях:

  1. GlobalsDB — универсальная NoSQL база данных. Часть 1,
  2. GlobalsDB — универсальная NoSQL база данных. Часть 2.

В рамках моей магистерской программы, был начат проект по реализации документо-ориентированной NoSQL на основе Cache. Теоретической исследовательской базой этого проекта является концептуальный вопрос о быстродействии, производительности и надежности такой реализации, по сравнению с существующим решением. В качестве опорной документо-ориентированной NoSQL была выбрана моя любимая MongoDB.

Итак, что же я имел в своем начале пути?

1. Документо-ориентированную NoSQL MongoDB.
2. Иерархическую NoSQL Cache.


^ Задача №1. Представление документов на иерархических структрах данных


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

Напомню, что JSON формат определяет 6 типов: null, number, string, true, false, array, object. Таким образом, требовалось придумать однозначную схему представления данных для каждого JSON типа, имя в распоряжении лишь возможность строить иерархии и использовать, в качестве значений для листов дерева, строки и числа. Однако, к схеме представления JSON данных выдвигалось еще одно требование — однозначность. Это условие — гарант однозначной восстанавливаемости JSON данных из глобалов.

Немного поясню этот момент.

Рассмотрим JSON тип null. Можно было бы предложить для него простую схему. Допустим, если есть значения типа JSON null, то при сохранении этого значения в глобал необходимо создать лист и установить в качестве значения пустую строку "". Однако, первый же контрпример приходит очень быстро, — схема теряет однозначность в тот момент, когда нам потребуется сохранить значение типа JSON string, равное пустой строке. В связи с этим я решил перейти на другую, довольно простую схему.

описание схемы
JSON null


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. Реализация драйвера


Реализация драйвера состоит из двух этапов:

  1. разработка хранимого кода (в Cache, на языке Cache ObjectScript),
  2. разработка кода, который будет обращаться к драйверу 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.

Для него реализованы два драйвера:

  1. NSNJSON Node.js Driver
  2. NSNJSON Java Driver


^ Заключение


Вот и подошла к концу заключительная статья о NSNJSON. Я рассказал о трудностях с которыми столкнулся, а также о том, как я их преодолел.
На последок, хочу еще раз отметить, что это был мой ? (путь), и я его прошёл именно таким образом. На каждом шаге можно было бы пойти по-другому, выбирая другой вариант решения возникавших проблем, но это был бы уже не мой путь…

Комментарии (15)


  1. vintage
    06.11.2015 08:34

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


  1. NeoCode
    06.11.2015 09:07

    В JSON все что не хватает — это комментариев.
    Я бы предложил такое:
    Однострочные //
    Многострочные /* */
    И блочные (для структурного комментирования скобочного блока) #


    1. vintage
      06.11.2015 10:19

      В JSON много чего не хватает. Прежде всего не хватает расширяемости.


      1. NeoCode
        06.11.2015 13:53

        О какой расширяемости идет речь? «Расширяемость» — слишком большое понятие.
        А так он свою функцию вполне выполняет.


        1. vintage
          06.11.2015 15:08
          +3

          О добавлении своих типов узлов. Приходится писать такие костыли: [ «date», «2015-11-11» ] или { «type»: «date», «value»: «2015-11-11» }


          1. mayorovp
            06.11.2015 22:22

            Добавлю в список костыль от Microsoft: "/Date(1234567)/"


          1. Eternalko
            10.11.2015 07:19

            Как хорошо что в JSON нет расширяемости!!!


            1. vintage
              10.11.2015 07:58

              Ну да, ведь шести типов хватит всем :-)


    1. mayorovp
      06.11.2015 22:21
      +1

      Блочный комментарий сделает JSON несовместимым с JS…


      1. Eternalko
        10.11.2015 07:24
        -1

        Для красоты и удобства могу присоветовать CSON. Coffescript JSON.
        Тот же JSON только в Coffee. Плюс в том что нет запятых и скобочек и все красиво.

        И вместо `require('config.json')` даем `require('config.cson')` и все.
        Очень удобно.


        1. mayorovp
          10.11.2015 08:57

          Да-да, очень. Особенно тем, кто никогда не писал require('config.json') :)


          1. Eternalko
            10.11.2015 18:58
            -1

            Писать в JS и не писать `require` немного странно )


            1. mayorovp
              10.11.2015 19:09

              Я не говорил, что не писал require (хотя в этом тоже нет ничего странного, всего лишь ручная сборка зависимостей). Я сказал, что никогда не загружал конфиг через require…

              Для справки: js — это не только сервер-сайд в виде node.js, некоторые люди еще и скрипты для браузера пишут :)


  1. tsafin
    06.11.2015 12:48
    +1

    FWIW. GAIA это не про NASA, а про ESA (European Space Agency).


  1. morisson
    06.11.2015 12:49

    Скажу лишь, что NASA использует InterSystems Cache в проекте GAIA.
    Поправочка: не NASA, а ESA.