Гугл предлагает усилить JSON с помощью Jsonnet

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

    Комментарии. Jsonnet принимает комментарии в стиле С ( /* … */ ) и С++ ( // )

    Ссылки. Ключевое слово self может быть использовано для ссылки на текущий объект. Оператор $ позволяет использовать корневой объект.

    Арифметические и условные операторы. Оператор + может складывать числа, строки, массивы и объекты. Операторы == и != возвращают true или false. Оператор if работает как тернарный оператор ?: в С. Далее несколько примеров с операторами языка и результат. Примеры взяты со страницы проекта.
    // bar_menu.3.jsonnet
    {
        foo: 3,     
        bar: 2 * self.foo,  // Multiplication.
        baz: "The value " + self.bar + " is "
             + (if self.bar > 5 then "large" else "small") + ".",
        array: [1, 2, 3] + [4],
        obj: {a: 1, b: 2} + {b: 3, c: 4},
        equality: 1 == "1",
    }
    

    Результат:
    {
       "foo": 3,
       "bar": 6,
       "baz": "The value 6 is large.",
       "array": [1, 2, 3, 4],
       "obj": {a: 1, b: 3, c: 4},
       "equality": false
    }
    

    Создание массивов и объектов. Для создания массивов и объектов используется конструкция с оператором for, как показано в примере ниже:
    {
        foo: [1, 2, 3],
        bar: [x * x for x in self.foo if x >= 2],
        baz: { ["field" + x]: x for x in self.foo },
        obj: { ["foo" + "bar"]: 3 },
    }
    


    Результат:
    {
       "foo": [ 1, 2, 3 ],
       "bar": [ 4, 9 ],
       "baz": {
          "field1": 1,
          "field2": 2,
          "field3": 3
       },
       "obj": { "foobar": 3 }
    }
    

    Модульность. Код написанный на Jsonnet может быть разбит на несколько файлов и затем объединятся с помощью оператора import. Внутренняя механика заключается в простом склеивании файлов.

    Функции. Jsonnet значения могут содержать функции. Они помечаются как скрытые поля и не транслируются в JSON. Пример такой функции представлен ниже:
    // bar_menu_utils.jsonnet
    {
        equal_parts(size, ingredients)::
            if std.length(ingredients) == 0 then
                error "No ingredients specified."
            else [
                { kind: i, qty: size/std.length(ingredients) }
                for i in ingredients
            ],
        id:: function(x) x,
    }
    

    Jsonnet также включает в себя локальные переменные, способ для наследования объектов путём импортирования, вычисляемые и опциональные поля.

    Движок языка написан на С++11 с предоставлением обёртки API в стиле С для более лёгкого портирования на другие языки. Команда разработчиков сразу может предоставить библиотеки для С и Питона. Реализация для С++ может быть скомпилирована в JS с Emscripten. Еще доступен неофициальный пакет для nodejs.

    Полные спецификации можно посмотреть на странице спецификации.

    Некоторое сравнение с другими языками


    JSON. Собственно, JSON описывает все данные буквально. Jsonnet имеет более свободный синтаксис и комментарии, для облегчения чтения данных людьми.

    YAML. Так же является некоторым расширением JSON, который позволяет генерировать правильный JSON. Синтаксис языка очень компактный и файлы на YAML гораздо, короче чем они потом выходят в JSON формате. Несмотря на то, что язык создан в тех же целях, что и Jsonnet, создание, трансляция и уточнение данных проигрывает Jsonnet. В частности, YAML и Jsonnet имеют различные точки зрения на то, что должно означать «1+1». YAML говорит, что это строка «1+1», тогда как Jsonnet считает, что результат должен быть 2.

    Другие языки с шаблонами. Jsonnet является шаблонным языком, который генерирует данные по алгоритмам с перемеживанием буквальных данных с вычислительными конструкциями. Большинство таких языков считают программы и результат простым текстом. Это значит, что на выходе может получится некорректный результат, если мы говорим о JSON. Большинство таких шаблонных языков не обладают знаниями о синтаксисе выходных данных и не могут проверять результат на правильность. Jsonnet такого недостатка лишён, так как это узкоспециализированный инструмент.

    Сравнение с другими инструментами и языками, такими как Haskel, Nix, Coil, Pystachio и другими можно в деталях прочитать в руководстве к Jsonnet.

    Вопросы и ответы


    В оригинальном топике появились интересные вопросы и ответы от ведущего разработчика проекта Дэвида Каннингэма (David Cunningham).

    Вопрос: Почему бы не воспользоваться уже существующим открытым стандартом EDN? На мой взгляд в нем есть все те же самые фичи и уже есть порты под разные языки.

    Ответ: Хороший вопрос, но EDN не очень-то похож на Jsonnet. EDN – это «только данные», он не знает ничего о вычислениях или абстракциях. Он расширяем, и вы можете добавить недостающие конструкции, но тогда вы получите по факту новый язык, который будет непонятен другим системам.

    Когда мы создавали Jsonnet, мы думали о том, что нам надо следовать общим стандартам. Мы выбрали JSON из-за его популярности, но мы так же пытались следовать существующим моделям программирования (главным образом js и python) так близко, как только возможно.

    Хочу также заметить, что можно интегрировать Jsonnet в системы, которые работают с EDN, потому что возможно генерировать EDN с помощью нашей системы. Необходимо только написать специальную функцию «manifest». Такая работа проделана для INI файлов, конфигурационных файлов Lua и Python.

    Наконец, Jsonnet доступна для 3х языков (С, Python, Javascript) и для любого языка, который может работать с С интерфейсом. Порты на другие языки запланированы, возможно с помощью портирования на Haxe.

    Вопрос. Мне очень нравится проект, но разработчики должны были использовать стандартные JavaScript функции, а не изобретать из в stdlib. Базовые функции пропущены и добавление новых не простая задача, так что это своего рода ограничитель и я, к сожалению, вернулся на старый предпроцессор JSON.

    Ответ. Stdlib определённо самая слабая часть проекта и то, что должно быть переписано, улучшено, и задокументировано прежде чем мы выпустим версию 1.0. Мы очень ждём ваших отзывов, особенно с примерами из реальной жизни.

    В целом есть возможность расширить stdlib самостоятельно и написать свою собственную библиотеку для Jsonnet. Пример ниже сначала использует маленький трюк для добавления метода add2 в stdlib:
    local std2 = std { // Temporarily define std2 to avoid self-reference.
       add2(x):: x + 2,
    };
    local std = std2; // Bind std2 over std.
    
    // Rest of Jsonnet file below:
    {
       foo: std.add2(10), // Expands to 12.
    }
    

    В общем случае, может быть невозможно скопировать функции из поддерживаемых языков, так как семантика может не иметь смысла в Jsonnet. Однако мы понимаем, что иметь необоснованные различия никому не поможет. И это является основной причиной, почему stdlib функции отвечающие за форматирование текста в точности совпадают с оператором % в Python.


    На основе материалов:

     
    И мы опять хотим привлечь ваше внимание к предстоящей конференции API & Backend (C#). Если вам есть что рассказать про детали реализации и управления API, сервисом на бэкенде. Если у вас есть интересные случаи связанные с генерацией сложных сообщений: заголовков и содержимого – мы ждем ваших историй!
    GeekFamily
    Company
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 67

      +11
      Комментарии. Jsonnet принимает комментарии в стиле С ( /* … */ ) и С++ ( // )


      Собственно, за отсутсвие комментариев в JSON можно сказать спасибо крокфорду с его шизофреническими идеями.
        +29
        Только этого мне не хватает в JSON. А все остальное из jsonnet на мой взгляд лишнее, т.к. это стандарт передачи данных, с которыми при необходимости может работать человек.
          +2
          А как же запятая? :)
            –2
            Дядя ты не праф, В ещё много чего не хватает. И это не стандарт передачи данных, а формат представления объекта данных.
            –6
            comment: «This is your comment»;

            Чем не устраивает?
              +7
              1. Корректен только в объектах/мапах.
              2. Является частью данных, при преобразовании будет полностью загружен в память (что нужно дополнительно обходить, если это проблема).
                –16
                Если ваши комментарии настолько забивают память, то я думаю, что проблема не в JSON…
                  +5
                  Суть в самом подходе, если вы ещё этого не поняли. В любом языке и синтаксисе (если он подразумевает работу с переменными) тогда можно таскать просто строковую переменную, к которой «присваивать комментарий». Можно в окна (вместо дверей) входить, а микроскопами гвозди забивать — да
                    –10
                    JSON это неструктурированные данные. Комментарий — часть данных. В чём проблема?
                      +2
                      Допустим вы делаете конфиг для программы. И у вас есть два варианта: либо конфиг будет без комментариев, либо программа должна будет загружать комментарии в рантайме в память. Это не нужно и это оверхед, т.к. программа держит в памяти то что ей не нужно.
                        –5
                        И сколько там она загрузит этих комментариев? Если вы пишите хардкорный embedded на asm, тогда, наверное, вам json в принципе не подходит, не то что комментарии в нём. А если вы пишите на каком-нибудь js, ruby или python то переживать из-за пары байт в комментарии явно не стоит.
                          –1
                          суть в том, что заранее неизвестно какой объем текста будет в комментариях. вы не можете утверждать, что его всегда будет «пару байт».
                            –4
                            Размер JSON вы тоже никогда не угадаете принципиально, так как у него нет схемы. Если вы используете JSON для данных, где можно определить схему, то you are doing it wrong.
                              0
                              У любого JSON есть неявная схема — это те представления о возможной структуре данных, которые писали программу, его генерирующую либо использующую.

                              Иногда эта схема даже описывается в документации.
                                0
                                Для справки:
                                www.google.ru/?q=json%20schema
                          • UFO just landed and posted this here
                              +2
                              По большому счету есть две проблемы с таким подходом:
                              1) Комментарии являющиеся частью JSON тратят ресурсы. Да, они бы тратили ресурсы в любом случае, но всетаки если бы они вырезались на уровне парсера тратили бы меньше чем если делать это на более высоком уровне. Да, это копейки, но мы сейчас говорим о концептуальной проблеме стандарта.
                              2) Нет единого синтаксиса или соглашения для комментариев. Можно договориться, например, добавлять комментарий в виде поля "_comment" в объекте, примерно так:
                              {
                                 _comment: "This is my program config file. Param 1 is for option1, param2 for option2",
                                param1: "value1",
                                param2: "value2"
                              }
                              

                              Такой синтаксис, во первых не позволяет написать отдельные комментарии к param1 и param2, например так:
                              {
                                // This is my program config file.
                                param1: "value1", // Option 1.
                                param2: "value2"  // Option 2.
                              }
                              

                              Во вторых нет поддержки «вырезания» таких комментариев на разных платформах, и если вы допустим пишете приложение с сервером на c# и клиентами на js, Java и Swift то вам придется написать четыре пусть и простых но прослойки которые будут вырезать _comment ноды из распарсеного дерева, или делать это на уровне тесктого препроцессора.
                              В третьих это не является стандартом и возможно в будущем вы столкнетесь с какой-то библиотекой или сторонним API которое использует поле _comment для каких-то своих целей, тогда вам придется как-то изворачиваться чтобы один JSON пропускать через вот этот парсер, а другой через другой.

                              Я не говорю что все эти проблемы нерешаемы или очень сложны, что нельзя прикрутить два парсера или что написать препроцессор очень сложно, но всем было бы удобнее, если бы комменатрии поддерживались в стандарте.
                              • UFO just landed and posted this here
                    0
                    Чем не устраивает?

                    Ну меня в вашем предложении больше всего не устраивает, что если нужно будет итерироваться по потомкам, то постоянно нужно будет проверять, не является ли у нас элемент комментарием. Причем насколько я знаю, с одним именем может быть только один элемент хеш-таблицы, коей является JSON, соответственно при желании добавить несколько комментариев в разных местах нужно будет проверять каждый элемент, не начинается ли он на comment, формировать культуру «комментарии начинайте со слова comment, например comment1, commentValue, ...», при малейшей опечатке превращается в camment, coment и т.п., в предметной области, ну например, объект — фильм на афише или блог, может быть поле comments, который придется отдельно обрабатывать, потому что его может порезать проверка на то, что слово начинается на это слово…

                    Можно продолжать сколько угодно. Причем это это не единственные недостатки вашего подхода, а только в добавление к вышесказанному.
                    +6
                    А можно ссылку на эту тему? Гугл не силён в запросах «Шизофренические идеи Крокфорда» и «Крокфорд против комментариев», а почитать интересно)
                  +11
                  Даёш Javascript в JSON
                    +6
                    Че мелочиться? Давайте сразу компилятор прикрутим к парсеру-JSON.

                      0
                      Скорее тогда javaton.
                    • UFO just landed and posted this here
                        +94
                        Господи, не надо трогать JSON, пусть останется хотя бы один простой и понятный текстовый формат, который железобетонно все поддерживают!

                        image
                          +16
                          Единственно, комментарии можно было бы добавить.
                            +1
                            Пусть добавят тип дата/время, и довольно. Можно ещё значение Infinity.
                              +4
                              не надо дату/время — нигде нет нормального стандарта. Используйте таймстамп лучше
                                  +1
                                  При всём наличии этих хороших стандартов всегда можно вспомнить о том, что Twitter (как явствует из примера, официально приведённого вон там) не стесняется возвращать время и дату в адском формате «Wed May 23 06:01:13 +0000 2007» (день недели, месяц, день, время, часовой пояс, год).
                            +5
                            Странно, что такое название выбрали, так как есть созвучная и популярная библиотека под .NET: Json.NET.
                              +5
                              Странно, что это в хабах ASP и .Net.
                                +2
                                Да и гугл по запросу jsonnet первые несколько результатов выдает про Json.NET.
                                +18
                                image
                                  +1
                                  Ух ты, в кои-то веки буханка в плюсах!
                                    +1
                                    Хабр уже не торт. Теперь он — хлеб.
                                  +5
                                  вопрос: а зачем?
                                    0
                                    > заменяет стандартный JSON и добавляет новые возможности без нарушения обратной совместимости. Среди таких возможностей: комментарии ...


                                    Для поддержки комментариев делал проект github.com/spmbt/jsonComm — формат с комментариями (одно- и многострочными) и возможность смены ключей и значений в парах «ключ-значение» без удаления комментариев. Хабр

                                    Он сейчас работает и расширен (код скоро будет добавлен в репо после тестирования) до возможности работы с фрагментами jsonComm в JS-файлах. Фрагменты выделяются специальными комментированными скобками с достаточно вольным синтаксисом.
                                      +6
                                      Ну, и кто (и когда) должен вычислять «1 + 1»?
                                      Генерирующая сторона в момент отправки?
                                      Читающая сторона в момент приема?
                                      А если json сохраняется в файл, нужно вычислять во время записи, или во время чтения?
                                        +1
                                        Это формат для конфигов. Разумеется, вычислять должна программа при чтении — просто потому что человек пишет.
                                          0
                                          JSON — это не формат для конфигов. Это формат обмена данными, и его применение конфигами не ограничивается.
                                            +1
                                            Зато применение Jsonnet ими ограничивается.
                                            Гугл открыла исходный код своего проекта Jsonnet, языка для конфигурации, который заменяет стандартный JSON и добавляет новые возможности без нарушения обратной совместимости.
                                            +4
                                            JSON — настолько же формат для конфигов, насколько AVI — формат для гей-порно.

                                            За все годы я только один раз использовал JSON для хранения конфигов, и этот JSON как писался машиной, так ей же и читался, человек (я) лишь один раз задал его формат в коде. Зато без использования JSON для передачи данных между какими-то сторонами не обходится нынче почти ни один проект, поскольку альтернатив, в общем-то, и нет (XML и основанные на нём стандарты в разы дороже по оверхеду).
                                            • UFO just landed and posted this here
                                                +1
                                                Могу в ответ лишь предложить им уволиться и сменить род деятельности, поскольку никакой разницы для разработчика, делать SOAP-сервис или JSON-сервис, в .NET нет, а использовать «все возможности фреймворка», скидывая на пользователей все неудобства, связанные с повышенным оверхедом, они могут в своё свободное время, делая личные проекты.
                                                • UFO just landed and posted this here
                                                +1
                                                Я писал не про JSON как бы
                                            +9
                                            JSON — формат обмена данными, у которого есть множество реализаций для самых разных языков программирования. Он как раз примечателен тем, что он не исполняем, а потому относительно безвреден, а вычислительные ресурсы по его преобразованию обычно близки к О(strlen(message)).

                                            Если нужно обрабатывать данные перед преобразованием в JSON — как раз существующие реализации покрывают эти нужды. Ведь если есть JSON, то где-то рядом работает и преобразователь между JSON и нативными типами (как правило). Добавлять ещё один язык в технологический стек нерационально или даже опасно.

                                            Я вижу только один адекватный способ применения: преобразование структуры JSON-документов — когда у нас есть только исходный документ и приёмник, в который надо послать документ с этими же данными, но в другой структуре. Больше я не вижу ситуаций, когда не используется реализация JSON на другом языке и потому есть свобода выбора. Но лично я даже в этой ситуации выбрал бы Ruby, Python (основы которого изучал бы на ходу, поскольку его не знаю) или JS/производные.
                                            • UFO just landed and posted this here
                                              +5
                                              Тот, кто говорит, что в YAML 1+1 — это строка «1+1» явно ничего не понимает в YAML. Нужно преобразовывать 1+1 в 2 — напишите свой resolver или constructor (второе обязательно, первое нет). Гораздо проще взять готовый YAML парсер и приделать к нему constructor, чем писать новый формат.

                                              Если что: resolver определяет, какой тёг соответствует данному синтаксическому дереву в случае, когда тёг не указан (здесь тёг — это тип). Обычно используется только для скаляров, именно благодаря resolver'ам в формате есть числа и true/false/null.

                                              Constructor определяет, как из синтаксического дерева получить объект (строку/число/словарь/...). Определение тёга определяет constructor.

                                              В стандарте описаны «стандартные» resolver'ы для трёх схем (безопасная, JSON-совместимая, основная (failsafe, json, core)), но нигде не написано, что они обязаны быть единственными.
                                              • UFO just landed and posted this here
                                                  +16
                                                  JSON это декларативный формат по свой сути. Зачем туда пихать императивные директивы вообще не понятно.
                                                    +4
                                                    XML-bomb сделать не проблема.
                                                    Теперь видимо можно будет и JSON-bomb сделать :-)
                                                      +1
                                                      Вот да, сразу возникают вопросы с безопасностью. Принимать JSON из недоверенного источника в принципе можно. Дыры в JSON-парсерах случаются очень редко. А тут сам формат подразумевает, что результат может вычисляться долго и захавает всю память.
                                                      +4
                                                      В json не хватает четырех вещей — схемы, дат, комментариев и NaN. А так — идеальный формат.
                                                        +1
                                                        Из всего вышеперечисленного для эффективной передачи данных не пригодится ничего (кроме, возможно, NaN). Схему передавать по сети (особенно мобильной) очень дорого, тем более, что предполагается, что общающиеся стороны знают про протокол обмена, и не крашатся от допустимых изменений (отсутствующее поле, значение null в любом из полей, новое поле). Если разработчик накосячил с типом, в который он хочет приводить поле — это не проблема формата передачи данных.

                                                        Самый простой способ избежать проблемы с кривыми руками и неверными типами — использовать схожие языки для обеих сторон (например, Java-фронтенд и C#-бекенд), и после фиксации протокола тупо копировать все структуры данных из сериализующего проекта в десериализующий, по пути исправляя синтаксис.

                                                        Даты и сейчас прелестно передаются в формате таймштампа. В случае, когда надо передать ещё и таймзону, её всё равно нельзя передавать цифрой +ЧЧММ после даты, а надо заводить отдельное строковое поле.
                                                          +1
                                                          Схему передавать и не надо — это просто стандратный способ проверить целостность данных, то есть вместо громоздкого текстового описания моего API и тучи реализаций на разных языках, я могу просто предоставить одну схему. Отсутствие схемы — это не минус самого формата, это минус его инфраструктуры, и хорошо, что json schema уже, как минимум, internet draft.

                                                          Для дат есть замечательный ISO 8601, самый распротраненный формат данных после строк и чисел. Иметь его в стандрате передачи данных было бы очень приятно.
                                                            +1
                                                            <нудная мутотень>

                                                            ISO 8601 прекрасен для случаев, когда надо передать отсылку на конкретную точку во времени, т.е. по сути, тот же таймштамп. Это прекрасно работает для дат в прошлом. Если же вы оперируете датами из будущего, это может быть неприемлемо. Например, пользователь сказал приложению «напомни мне захватить мир 5 января 2020 года в 11:00», после чего вы сохранили это таймштампом (или в ISO 8601, разницы нет). Через два года прилетает новая tzdata, таймзона пользователя меняет часовой пояс или параметры DST, и представление «5 января 2020 года в 11:00» теперь указывает на другую точку во времени. Но вы об этом не узнаете, и напоминание откроете не в 11:00, а в другое время. Ошибочка вышла…

                                                            </нудная мутотень>

                                                            Как передавать и хранить дату, надо решать в каждом случае отдельно, в первую очередь отталкиваясь именно от того, что нам нужно зафиксировать — точку во времени (таймштамп), или пользовательское представление о будущей дате (ISO 8601 + название таймзоны). В любом случае, как вы договоритесь делать в протоколе передачи, так можно и передавать, все существующие форматы дат, включая ISO 8601, отлично вписываются в строки.
                                                        +1
                                                        Да таких проектов уже тьма… есть например HOCON… Но новый язык это как-то слишком имхо для задачи «json на выходе».
                                                          +6
                                                          Уу, в этом месяце еще никто не изобретал JSON с комментами!
                                                            +1
                                                            Мы изобретём новый json с блекджеком комментариями и арифметическими операторами © Google
                                                              0
                                                              Они были недостаточно креативны с комментами. Вот перловый модуль JSON в relaxed-режиме не только допускает end-commas в списках, но и комменты, начинающиеся с #:

                                                              search.cpan.org/~makamaka/JSON-2.90/lib/JSON.pm#relaxed
                                                                +1
                                                                Любой синтаксис файлов конфигурации со временем превращается в полноценный язык программирования.
                                                                0
                                                                del

                                                                Only users with full accounts can post comments. Log in, please.