Статья написана в сентябре 2017 года



JSON захватил мир. Если сегодня любые два приложения общаются друг с другом через интернет, то скорее всего делают это с помощью JSON. Стандарт принят всеми крупными игроками: из десяти самых популярных Web API, которые разработаны в основном крупными компаниями, такими как Google, Facebook и Twitter, только один API передаёт данные в XML, а не JSON. Для примера, Twitter поддерживал XML до 2013 года, когда выпустил новую версию API исключительно на JSON. Среди остальных разработчиков JSON тоже популярен: согласно Stack Overflow, о JSON задаётся больше вопросов, чем о любом другом формате обмена данными.

XML ещё жив и много где используется. Например, в веб-форматах SVG, RSS и Atom. Если автор Android-приложения хочет объявить, что тому требуется разрешение от пользователя, то делает это в манифесте приложения, написанном на XML. И XML — не единственная альтернатива JSON: некоторые разработчики делают выбор в пользу YAML или Protocol Buffers от Google. Но эти форматы далеко не так популярны, как JSON, который сейчас стал практически стандартом де-факто для обмена данными между программами через интернет.

Доминирование JSON удивительно, ведь ещё в 2005 году все обсуждали потенциал «асинхронного JavaScript и XML», а не «асинхронного JavaScript и JSON». Конечно, есть вероятность, что это ничего не говорит об относительной популярности двух форматов, просто AJAX казался более привлекательной аббревиатурой, чем AJAJ. Но хотя в 2005 году некоторые уже использовали JSON вместо XML (на самом деле мало кто), до сих пор задаёшься вопросом, как XML мог так резко упасть, что спустя десятилетие фраза «асинхронный JavaScript и XML» вызывает ироническую усмешку. Что произошло за это десятилетие? Как JSON заменил XML во многих приложениях? И кто придумал этот формат данных, от которого теперь зависят инженеры и системы во всём мире?

Рождение JSON


Первое сообщение в формате JSON было отправлено в апреле 2001 года с компьютера в гараже неподалёку от Сан-Франциско. История сохранила имена причастных к событию: Дуглас Крокфорд и Чип Морнингстар, соучредители технологической консалтинговой компании State Software.

Эти двое занимались разработкой AJAX-приложений задолго до появления термина AJAX. Но поддержка приложений в браузерах была не очень хорошей. Они хотели передать данные в своё приложение после начальной загрузки страницы, но не нашли способа, который работал бы во всех браузерах.

Сегодня трудно поверить, но Internet Explorer в 2001 году был самым передовым браузером. Ещё с 1999 года Internet Explorer 5 поддерживал раннюю форму XMLHttpRequest через ActiveX. Крокфорд и Морнингстар могли применить эту технологию для получения данных в приложении, но она не работала в Netscape 4. Таким образом, пришлось искать другой формат, который работал в обоих браузерах.

Первое сообщение JSON выглядело так:

<html><head><script>
    document.domain = 'fudco';
    parent.session.receive(
        { to: "session", do: "test",
          text: "Hello world" }
    )
</script></head></html>

Только небольшая часть сообщения напоминает JSON, каким мы его знаем сегодня. Само сообщение на самом деле представляет собой HTML-документ с парой строчек JavaScript. Часть, похожая на JSON, — просто литерал JavaScript для функции receive().

Крокфорд и Морнингстар решили злоупотребить фреймом HTML для отправки данных. Для фрейма можно указать URL, который вернёт HTML-документ, подобный приведённому выше. Когда HTML получен, JavaScript запускается и передаёт литерал обратно в приложение. Это работало при условии аккуратного обхода защиты браузера, предотвращающей доступ дочернего окна к родительскому: как видите, Крокфорд и Морнингстар явно установили домен документа. Такая техника иногда называется скрытым фреймом, она часто использовалась в конце 90-х до появления нормального XMLHttpRequest.

В первом сообщении JSON удивительно то, что здесь вообще не очевидно, что это первое использование нового вида формата данных. Тут всего лишь JavaScript! На самом деле идея использования JavaScript таким образом настолько проста, что сам Крокфорд считает, что он не первый это сделал — он утверждает, что кто-то в Netscape использовал литералы массива JavaScript для передачи информации ещё в 1996 году. Сообщение на простом JavaScript не требует какого-либо специального парсинга. Всё делает интерпретатор JavaScript.

На самом деле у первого в истории JSON-сообщения возникли проблемы с интерпретатором. JavaScript резервирует огромное количество слов — в ECMAScript 6 зарезервировано 64 слова — и Крокфорд и Морнингстар невольно использовали их в своём сообщении: а именно, зарезервированное слово do в качестве ключа. Поскольку в JavaScript так много зарезервированных слов, Крокфорд решил не избегать их, а просто закавычивать все ключи JSON. Закавыченный ключ рассматривается интерпретатором JavaScript как строка, так что можно спокойно использовать зарезервированные слова. Вот почему ключи JSON по сей день закавычены.

Крокфорд и Морнингстар поняли, что новый метод можно использовать во всех видах приложений. Они хотели назвать формат JSML (JavaScript Markup Language), но оказалось, что аббревиатура уже занята чем-то под названием Java Speech Markup Language. Поэтому выбрали Javascript Object Notation, то есть JSON. Они начали предлагать формат своим клиентам, но вскоре выяснилось, что те не рискуют использовать неизвестную технологией без официальной спецификации. Поэтому Крокфорд решил написать её.

В 2002 году Крокфорд купил домен JSON.org, опубликовал синтаксис JSON и пример реализации парсера. Веб-сайт до сих пор работает, хотя теперь демонстрирует ссылку на стандарт JSON ECMA, принятый в 2013 году. Кроме запуска сайта, Крокфорд практически ничего не предпринял для продвижения JSON, но вскоре появились реализации парсера JSON на самых разных языках программирования. Изначально JSON был явно связан с JavaScript, но затем стало понятно, что он хорошо подходит для обмена данными между произвольными парами языков.

Неправильный AJAX


JSON получил большой толчок в 2005 году. Тогда дизайнер и разработчик по имени Джесси Джеймс Гарретт в своей статье ввёл в обращение термин AJAX. Он старался подчеркнуть, что AJAX — не какая-то одна новая технология, а скорее «несколько по-своему хороших технологий, объединённых мощными новыми способами». Новому подходу к разработке веб-приложений Гарретт дал название AJAX. В блоге он рассказал, как разработчики могут использовать JavaScript и XMLHttpRequest для создания более интерактивных приложений. Он назвал Gmail и Flickr примерами сайтов, опирающихся на методы AJAX.

Конечно, «X» в AJAX означало XML. Но в последующих вопросах и ответах Гарретт назвал JSON вполне приемлемой альтернативой. Он писал, что «XML является наиболее функциональным средством обмена данными для клиента AJAX, но того же эффекта можно достичь с помощью Javascript Object Notation или любого подобного формата структурирования данных».

Разработчики действительно обнаружили, что могут легко использовать JSON для создания приложений AJAX, и многие выбрали его вместо XML. По иронии судьбы, интерес к AJAX привёл к взрыву популярности JSON. Примерно в это время JSON привлёк внимание блогосферы.

В 2006 году Дейв Уайнер, плодовитый блогер и создатель ряда XML-технологий, таких как RSS и XML-RPC, пожаловался, что JSON заново изобретает XML без уважительной причины:

«Конечно, я могу написать процедуру для парсинга [JSON], но посмотрите, как далеко они зашли в повторном изобретении технологии: по какой-то причине XML недостаточно хорош для них (интересно, почему). Кто создал эту пародию? Давай найдём дерево и повесим парня. Прямо сейчас».

Легко понять разочарование Уайнера. XML никогда особо не любили. Даже сам Уайнер сказал, что ему не нравится XML. Но XML был разработан как универсальная система для любых приложений, какие только можно вообразить. XML на самом деле является метаязыком, который позволяет определять доменные языки для отдельных приложений — например, RSS и SOAP. Уайнер считает, что важно выработать консенсус ради всех преимуществ, которые несёт общий формат обмена. По его мнению, гибкость XML в состоянии удовлетворить любые потребности. И всё же вот JSON — формат, не предлагающий никаких преимуществ по сравнению с XML, за исключением очистки от хлама, который сделал XML настолько гибким.

Крокфорд увидел сообщение в блоге Уайнера и оставил комментарий. В ответ на обвинение в том, что JSON заново изобретает XML, Крокфорд написал: «Повторное изобретение колеса хорошо тем, что можно сделать его круглым».

JSON vs XML


К 2014 году JSON официально признали стандартом ECMA и RFC. Он получил свой тип MIME. JSON вышел в высшую лигу.

Почему JSON стал намного популярнее XML?

На JSON.org Крокфорд перечисляет некоторые преимущества JSON по сравнению с XML. Он пишет, что JSON легче для понимания и людьми, и машинами, поскольку его синтаксис минимален, а структура предсказуема. Другие блогеры упоминают многословие XML и «налог на теги». Каждому открывающему тегу в XML должен соответствовать закрывающий тег, что означает много избыточной информации. Это делает XML намного больше эквивалентного документа JSON, но ещё важнее, что из-за этого XML-документ труднее читать.

Крокфорд называл ещё одно большое преимущество JSON: то, что он изначально разработан как формат обмена структурированной информации между программами. Хотя XML использовали для той же цели, но изначально он разработан как язык разметки документа. Он вырос из SGML (Standard Generalized Markup Language), который, в свою очередь, эволюционировал из языка разметки Scribe, предназначенного для разметки текста, как LaTeX. В XML внутри тега может находиться так называемое «смешанное содержимое», то есть текст со встроенными тегами, окружающими слова или фразы. Это напоминает редактора, помечающего рукопись красным или синим маркером, своеобразная метафора для языка разметки. С другой стороны, JSON не поддерживает точный аналог смешанного контента, что означает упрощение структуры. Документ лучше всего представить в виде дерева, но отказавшись от идеи документа, Крокфорд смог ограничить JSON словарями и массивами знакомых элементов, которые все программисты используют в создании своих программ.

Наконец, моя собственная догадка заключается в том, что людям не нравилась запутанность XML, и он действительно был таким из-за своего разнообразия. На первый взгляд трудно различить грань между собственно XML и его субъязыками, такими как RSS, ATOM, SOAP или SVG. Первые строки типичного XML-документа устанавливают версию XML, а затем конкретный подязык, которому должен соответствовать XML-документ. Это уже много вариантов по сравнению с JSON, который настолько прост, что никакая новая версия спецификации JSON никогда не будет написана. Разработчики XML в попытке создать единый формат обмена данными для всего пали жертвой классической ловушки программиста: чрезмерного технического усложнения. XML настолько общий, что его трудно использовать для чего-то простого.

В 2000 году началась кампания по приведению HTML в соответствие со стандартом XML. Опубликовали спецификацию для XML-совместимого HTML, впоследствии известного как XHTML. Некоторые производители браузеров сразу начали поддерживать новый стандарт, но быстро стало очевидно, что широкая публика, работающая с HTML, не желает менять свои привычки. Новый стандарт требовал более строгой проверки XHTML, чем было принято для HTML, но слишком многие сайты зависели от вольных правил HTML. К 2009 году активисты прекратили попытки написать вторую версию XHTML, когда стало ясно, что будущее за стандартом HTML5, который не требовал соответствия XML.

Если бы усилия XHTML увенчались успехом, возможно, XML стал бы общим форматом данных, как надеялись его разработчики. Представьте себе мир, в котором у HTML-документов и ответов API в точности одинаковая структура. В таком мире JSON, возможно, не стал бы таким популярным, как сегодня. Но я считаю провал XHTML своего рода моральным поражением лагеря XML. Если XML не помог HTML, возможно, есть лучшие инструменты и для других приложений. В реальном мире легко понять, почему простой и узкоспециализированный формат JSON получил столь большой успех.

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


  1. DrPass
    29.08.2018 16:02
    +9

    JSON — это тот чудесный редкий случай в IT, когда простой и элегантный формат вытесняет сложный, навороченный, но более функциональный. Обычно бывает наоборот.


    1. OnYourLips
      30.08.2018 09:41

      Наоборот тоже происходит, посмотрите на yaml.
      Сложнее учится, сложнее парсится, зато легче читается, удобен в VCS, совместим с json.


      1. chupasaurus
        30.08.2018 13:53

        Несовместим он с JSON, но легко конвертируется.


        1. TonyLorencio
          30.08.2018 14:10
          +1

          Все-таки YAML это надмножество JSON, так что валидный JSON также является валидным YAML.


          1. chupasaurus
            30.08.2018 17:20

            Что не противоречит моему комментарию. «Голого» дефиса без кавычек в JSON нет, например.


    1. mSnus
      30.08.2018 15:31
      +1

      Всё ещё впереди. Поначалу Flash тоже был простой штукой и позволял просто делать милые анимации. Потом люди сказали — а давайте все улучшим, правда, придётся немного усложнить. И усложнили так, что Flash издох, не оставив альтернатив — слишком навороченной и сделай и сложной получилась поделка. Удержатся ли люди от "улучшения и усложнения" — только со временем увидим.


      1. khim
        30.08.2018 21:53

        Флешу чуть больше 20 лет, JSON — порядка 15. То есть если бы такие тенденции были — то они бы уже проявились. Но… За всё это время предложения «улучшнить и усложнить» высказывались много раз — и так же много раз «посылались».

        Просто потому что все понимают — JSON есть JSON, а начни «улучшать» и конца-края не будет.


  1. CheY
    29.08.2018 16:02

    Сравнение на графике какое-то безумное) могли бы ещё добавить HTML, plain text, xlsx, blob'ы. Почему бы и нет? Могут ведь! Главное чтобы JSON был выше всех


    1. justhabrauser
      29.08.2018 20:56
      -1

      Потому что задача статьи — «Шок! Видео! Трепет! Скандалы!»
      «Редактор GT» — оно такое. Это их работа.

      Не стреляйте в пианиста.


  1. excentro
    29.08.2018 16:42

    Ну и в банках много где только XML.


    1. hMartin
      30.08.2018 11:57

      Именно, а самая частая ошибка при реализации доработок — забыть согласовать с потребителем/поставщиком XSD и долго с этим упражняться потом. Большинство из-за этого делают резиновые XSD, что влечет за собой бессмысленность валидации :(
      (что, однако, не спасает от ошибок при очередных изменениях формата взаимодействия между системами)


  1. vics001
    29.08.2018 17:17
    +5

    Добавили бы в json комментарии, а то другие опять колесо изобретают yaml, hcl…


    1. PAE
      29.08.2018 17:28

      Уже "придумали" суперсет для JSON, так называемый JSON5.


      Разумеется, станет ли это распространённым или нет — вопрос, но самые "болезненные" недостатки обозначены — trailing commas, отсутствие ссылок и комментариев.


      Мне кажется — что нет, не станет. Проще использовать HCL [для людей], который полностью конвертируем в JSON [для машин и людей].


      1. khim
        29.08.2018 20:43
        +1

        Отсутствие ссылок и комментариев — это преимущество, а не недостаток.

        Спросите себя: если комментарий, который вы хотите прибавить к данным, настолько неважен, что его никто-никто и никогда не должен видеть — то зачем он вам? А если комментарий всё-таки может быть полезен для обработки (пусть иногда) — то что мешает его сделать отдельным полем 'notes', который большинство пользователей будет игнорировать?

        Ссылки, также, проблема: если вам где-то нужна ссылка, то заведите ЯВНОЕ поле URL и обрабатывайте его ЯВНО. Не создавайте пользователям странных и неожиданных обращений в сеть там, где их быть не должно.

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


        1. KvanTTT
          29.08.2018 20:57

          Спросите себя: если комментарий, который вы хотите прибавить к данным, настолько неважен, что его никто-никто и никогда не должен видеть — то зачем он вам? А если комментарий всё-таки может быть полезен для обработки (пусть иногда) — то что мешает его сделать отдельным полем 'notes', который большинство пользователей будет игнорировать?

          Ну например если есть задача сделать строгую схему данных, в которой запрещены опциональные свойства.


          1. gudvinr
            29.08.2018 21:51

            Для валидации ведь есть, как минимум, JSON Schema.
            Если этого требует какая-то частная задача — можно попотеть и написать/поискать валидатор.


            От того, что вы добавите строгую схему данных в условном JSON 2.0 и запретите опциональные свойства, конечные потребители не станут следовать этим правилам ввиду того, что уже есть тонны реализаций каноничного JSON, и ни в одночасье, ни в обозримой перспективе они не перейдут на новый стандарт, потому что "работает — не трожь".


            Тем более, что немало реализаций поддерживают де-/сериализацию JSON с учётом требований, о которых вы говорите, правда, не на уровне спецификаций JSON, а на стороне библиотеки.


          1. Vorber
            29.08.2018 22:13

            Схема и документ сущности всё-таки разные. И JSON-schema как раз позволяет (и по-умолчанию даже побуждает) описывать как раз такие форматы документов у которых нет опциональных свойтв в объектах.


        1. PAE
          29.08.2018 21:02
          +1

          Спросите себя: если комментарий, который вы хотите прибавить к данным, настолько неважен, что его никто-никто и никогда не должен видеть — то зачем он вам?

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


          Комментарии нужны, если JSON будет просматриваться, редактироваться и адаптироваться людьми под какие-то свои нужды.


          Ссылки, также, проблема: если вам где-то нужна ссылка, то заведите ЯВНОЕ поле URL и обрабатывайте его ЯВНО. Не создавайте пользователям странных и неожиданных обращений в сеть там, где их быть не должно.

          Речь не про URL, вообще не об этом. Речь про возможность сослаться на другие переменные (параметры) или шаблонизировать (аналогии — надстройки над CSS).


        1. xmetropol
          29.08.2018 21:10

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


        1. justboris
          29.08.2018 22:50
          +2

          Пару примеров, где комментарии в JSON могут быть полезными.


          1) Настраиваю какую-то систему, играюсь с конфигом. Пусть это будет tsconfig.json, например. Иногда хочется быстро отключить пару опций, что-то потестить и включить обратно. Было бы удобно включать/отключать при помощи комментов:


          {
              "compilerOptions": {
                  "module": "commonjs",
                  //"noImplicitAny": true,
                  //"sourceMap": true
              }
          }

          2) Когда наконец-то нашел подходящее сочетание параметров, хочется оставить какое-то объяснение будущим разработчиком, что же здесь стоит именно такое значение:


          {
              "compilerOptions": {
                  // use legacy module format until migration is complete
                  "module": "commonjs",
              }
          }

          К счастью, все это возможно в Typescript, потому что он поддерживает комментарии в JSON-синтаксисе.


          1. xmetropol
            29.08.2018 23:22

            К счастью, все это возможно в Typescript, потому что он поддерживает комментарии в JSON-синтаксисе.

            Честно говоря, это похоже на ситуацию, когда лохматые гвоздики шурупы пытаются забивать молотком в гипсокартон. Т.е. вот даже из статьи вроде как выходит JSON появился на свет не как грамотно продуманное решение, а скорее как некий костыль для решения определенной задачи в условиях существующих на тот момент технологий (кстати отдаленно напоминает историю создания одного популярного языка программирования). Но сейчас в защиту преподносятся аргументы перед XML, такие как простота, выразительность, элегантность и т.д. Вот только незадача, не хватает комментариев и прочих вещей (может однажды и CDATA переизобретут), которые так нужны сейчас в решении несвойственных данному формату задач. Поэтому давайте доделывать всякие костыли, из которых, возможно, когда-нибудь получится XML. У меня всё чаще складывается ощущение, что я где-то пропустил свою остановку.


            1. justboris
              29.08.2018 23:50

              Если использовать JSON только для общения сервера с клиентами, то комменты не нужны. Наоборот, чем меньше данных передается, тем лучше.

              А вот в конфигурационных файлах нужно комментировать, почему настроено именно так, а не иначе. В каком формате вы обычно пишете конфигурацию?


              1. xmetropol
                29.08.2018 23:59

                Вы точно у меня хотели спросить? Я думал по моему комментарию очевидно будет, что я не фанат JSON от слова «совсем». Я согласен с комментатором ниже, что конфиг в JSON — злое зло. Мой выбор XML. И этот выбор применителен не только к описанию конфигурации.


                1. andreymal
                  30.08.2018 01:10

                  (мимо пробегал: для конфигов есть toml, ну или упомянутый в посте yaml)


                1. justboris
                  30.08.2018 10:44
                  +2

                  Я в свое время достаточно наредактировался файлов pom.xml, чтобы больше не хотеть пользоваться этим форматом. Или у вас есть рецепт, как писать конфигурацию на xml, чтобы было компактно и читаемо, а не вот это?


                  <plugins>
                    <plugin>
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-source-plugin</artifactId>
                      <executions>
                        <execution>
                          <id>attach-sources</id>
                          <goals>
                            <goal>jar</goal>
                          </goals>
                        </execution>
                      </executions>
                    </plugin>
                  </plugins>

                  4 строки значимой информации из 14. Такой конфиг почти как человек — на 70% состоит из воды.


                  1. mayorovp
                    30.08.2018 11:39

                    Если такой формат перевести на JSON один в один, вы тоже не обрадуетесь.


                    А сократить можно было бы как-нибудь вот так:


                        <plugin groupId="org.apache.maven.plugins" artifactId="maven-source-plugin">
                            <execution id="attach-sources">
                                <goal>jar</goal>
                            </execution>
                        </plugin>


                    1. mrsantak
                      30.08.2018 15:30

                      Это будет работать до тех пор пока у вас один plugin, один execution и один goal (ну или если под execution не может лежать ничего кроме goal, под plugin — ничего кроме execution и т.д.).


                      1. mayorovp
                        30.08.2018 16:00

                        Нет, это будет работать с произвольным числом произвольных элементов. Нет никаких проблем писать вот так:


                        <plugin ...>
                            <execution>...</execution>
                            <execution>...</execution>
                            <execution>...</execution>
                            <execution>...</execution>
                            <foo>...</foo>
                            <foo>...</foo>
                            <bar>...</bar>
                        </plugin>


                        1. TerraV
                          30.08.2018 16:04

                          А теперь уговорите сообщество перейти на этот формат. Про что вам собственно и говорят. XML это или мысль в камне или аццкая боль переделки.


                          1. mrsantak
                            30.08.2018 16:07

                            Переделать как раз не проблема — в данном случае идет речь о xml покрытом хорошей xsd схемой, сконвертировать один формат в другой несложно каким-нибудь xslt.


                          1. mayorovp
                            30.08.2018 16:45

                            А вы тогда уговорите сообщество перейти на JSON. Про что я собственно и говорю, что проблема не в XML, а в выбранной схеме.


                        1. mrsantak
                          30.08.2018 16:05

                          Оно будет работать в том смысле, что распарсится, но оно не очень будет работать с точки зрения читаемости. Вот у plugin может быть произвольное кол-во execution и dependency. Если не использовать обертки типа executions и dependencies, то вы получите мешанину из execution и dependency в произвольном порядке. В итоге полученная «оптимизация» улучшает только простейший конфиг, но ухудшает читаемость реальных конфигов.

                          И вы же понимаете что то что вы написали со временем выродится в

                          <plugin ...>
                              <execution>...</execution>
                              <foo>...</foo>
                              <execution>...</execution>
                              <bar>...</bar>
                              <bar>...</bar>
                              <foo>...</foo>
                              <execution>...</execution>
                              <execution>...</execution>
                          </plugin>


                          1. mayorovp
                            30.08.2018 16:13

                            Да, я это понимаю. И считаю что нужно сознательно дать возможность пишущему конфиг писать элементы в том порядке в котором ему будет удобнее.


                            Но если вы считаете по-другому — ничто не мешает и потребовать строгого порядка элементов, в XSD есть все инструменты для этого.


                            Что же до формата реальных конфигов — я все еще не верю что от слепого преобразования в JSON они выиграют в удобочитаемости.


                            1. mrsantak
                              30.08.2018 16:18

                              Что же до формата реальных конфигов — я все еще не верю что от слепого преобразования в JSON они выиграют в читаемости.
                              Так ведь с этим никто вроде и не спорит. У json свои проблемы, у xml — свои.


                              1. mayorovp
                                30.08.2018 16:25

                                Да нет, в этой ветке как раз сравнивают форматы JSON и XML применительно к задаче написания конфигов на примере конфигов Typescript Compiler и Maven, против чего я и возражаю.


                  1. ris58h
                    30.08.2018 15:35

                    У нас есть плагин.


                    1. mrsantak
                      30.08.2018 16:11

                      Ну если для «человекочитаемого» формата нужен специальный редактор, чтобы его было удобно читать, то что-то не так с этим форматом.


                      1. ris58h
                        30.08.2018 21:44

                        Это проблема многословности схемы самого Maven, а не формата (это как раз рядом обсуждают). И плагин решает именно эту проблему, и не какую-то ещё.


                  1. xmetropol
                    30.08.2018 17:12
                    +1

                    Хотя Вам уже ответили, но вот 2 версии вашего конфига:
                    xml


                    <plugins>
                        <plugin groupId="org.apache.maven.plugins" 
                                artifactId="maven-source-plugin">
                            <executions>
                                <execution id="attach-sources">
                                    <goals>
                                        <goal>jar</goal>                
                                    </goals>
                                </execution>        
                            </executions>
                        </plugin>   
                    </plugins>

                    json


                    {
                      "plugins": [
                        {
                          "groupId": "org.apache.maven.plugins",
                          "artifactId": "maven-source-plugin",
                          "executions": [
                            {
                              "id": "attach-sources",
                              "goals": [
                                {
                                  "goal": "jar"
                                }
                              ]
                            }
                          ]
                        }
                      ]
                    }

                    Что в xml версии больше "шума", так это факт, я спорить не буду. Но лично мне xml версия больше нравится.


                    1. taujavarob
                      30.08.2018 20:54

                      Моя версия:

                      {
                        "plugins":
                          [
                            {"org.apache.maven.plugins":
                                {
                        	    "maven-source-plugin":
                                    {
                      	        "executions":
                                        [
                      	            {
                      		      "attach-sources":
                                              {
                      		          "goals": ["jar"]
                      		         }
                      	             }
                       	          ]
                      	      }
                                }
                            }
                          ]
                      }
                      

                      Или же перепишем это одной строкой:

                      {"plugins": [{"org.apache.maven.plugins": {"maven-source-plugin": {"executions": [{"attach-sources": {"goals": ["jar"]}}]}}}]}
                      


                      Если строка длинная, то можно переписать и так:
                      {"plugins": [
                        {"org.apache.maven.plugins":
                          {"maven-source-plugin":
                            {"executions": [
                              {"attach-sources": {"goals": ["jar"]}}]
                            }
                          }
                        }]
                      }
                      


                      P.S.
                      Мы неявно(!) задаём ID («org.apache.maven.plugins», «maven-source-plugin», «attach-sources») по правилу:

                      Eсли значение свойства есть объект (исключая массив), то имя этого свойства есть ID это объекта.

                      Если у объекта есть два и более ID, в данном случае «groupId» и «artifactId», вначале указываем самое «верхнее», а потом то что «ниже» этого самого «верхнего» и т.д. (применительно к расположению в изначальном xml).


                      1. xmetropol
                        30.08.2018 21:36

                        Вы сейчас придумали оптимизацию, которая сэкономила на 1-м названии свойства для каждого объекта (Id). Зато сломали мозг пользователям, которые без вашего объяснения не будут знать, как править конфиг, а так же заставив разработчиков написать вручную десериализаторы для чтения таких конфигов т.к. я думаю ни в Java (для которой собственно и был пример приведён), ни в C#, ни в любом другом языке по умолчанию сериализаторы не будут знать о ваших оптимизациях.


                        1. taujavarob
                          31.08.2018 20:57

                          xmetropol

                          Зато сломали мозг пользователям, которые без вашего объяснения не будут знать, как править конфиг
                          Они будут руководствуясь правилом: Eсли значение свойства есть объект (исключая массив), то имя этого свойства есть ID это объекта.

                          vintage
                          Ну и для сравнения то же самое на tree:
                          Ваша идея подсказала дальнейшее изменение моего кодa:

                          {"plugins":
                            {"org.apache.maven.plugins":
                              {"maven-source-plugin":
                                {"executions": 
                                  {"attach-sources": {"goals": "jar"}}
                                }
                              }
                            }
                          }
                          

                          Или одной строкой:
                          
                          {"plugins":{"org.apache.maven.plugins":{"maven-source-plugin": {"executions":{"attach-sources": {"goals": "jar"}}}}}}
                          


                          Здесь правило простое: Если ожидается массив, а вместо этого «поступает» объект или «примитивный» тип данных, то это можно рассматривать как массив с единственным элементом.

                          Что теряем?
                          В исходном:
                           <groupId>org.apache.maven.plugins</groupId>
                           <artifactId>maven-source-plugin</artifactId>
                          

                          не имеет значения порядок, можно писать и так:
                           
                          <artifactId>maven-source-plugin</artifactId>
                          <groupId>org.apache.maven.plugins</groupId>
                          

                          В моём предложении порядок имеет значение.

                          Но замечу, что
                           <groupId>org.apache.maven.plugins</groupId>
                           <artifactId>maven-source-plugin</artifactId>
                          

                          Фактически есть указание составного ID.

                          Да, при внесении нового ID, например:
                           
                          <superGroupId>org.apache.maven</groupId>
                          <groupId>org.apache.maven.plugins</groupId>
                          <artifactId>maven-source-plugin</artifactId>
                          

                          Также у меня поломает всё.


                    1. vintage
                      30.08.2018 21:15
                      -2

                      Ну и для сравнения то же самое на tree:


                      plugin
                          groupId \org.apache.maven.plugins
                          artifactId \maven-source-plugin
                          execution
                              id \attach-sources
                              goal \jar


                      1. mayorovp
                        31.08.2018 06:21

                        А куда делся знак =?


                        1. vintage
                          31.08.2018 06:27

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


                          1. mayorovp
                            31.08.2018 06:35

                            Вот в этом и (еще одна) проблема языка tree — вы его меняете как пожелаете и держите изменения синтаксиса в секрете.


                            1. vintage
                              31.08.2018 06:48

                              Не было никакого секрета. А как показало обсуждение без данного изменения у формата нет никаких шансов обрести популярность.


                              1. mayorovp
                                31.08.2018 06:51

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


              1. Aries_ua
                30.08.2018 10:07

                Если вы используете JS стек технологий, то напишите конфигурацию в JS файле. К примеру:

                // file settings.js
                const settings = {
                  host: 'localhost',
                  port: 3000
                };
                
                export default Object.freeze(settings);
                


                Для Python использовал подобную схему со словарями.


                1. justboris
                  30.08.2018 10:31

                  Да, это самый лучший вариант.


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


                1. MikailBag
                  30.08.2018 16:22

                  При этом вы теряете возможность менять конфиг не вручную. Например, скриптом для миграции.


            1. michael_vostrikov
              30.08.2018 06:14

              может однажды и CDATA переизобретут

              А зачем? CDATA для произвольных данных бесполезен, потому что в них может встретиться ]]>. Все равно надо делать специальную обработку, проще уж что-то типа htmlspecialchars() использовать. Для JSON чтобы не сломать разметку можно использовать ту же самую функцию, что его генерирует, в PHP это json_encode(). Там строки в кавычках, я бы даже сказал, <![CDATA[ и ]]> это переизобретение кавычек для строк. Если вы имеете в виду конфиги, то там бы конечно пригодилось, но в JSON это будет проще выглядеть, что-то типа "key": @"value"@. Так что XML все равно останется сложным и неудобным форматом.


          1. khim
            30.08.2018 01:55

            И всё это чудесным образом похерится как только кто-то откроет ваш конфиг а каком-нибудь визуальном редакторе JSON'а и сохранит его.

            Совершенно непонятно что мешает сдать так:

            {
                "compilerOptions": {
                    "module": "commonjs",
                    "noImplicitAny": false,
                    "sourceMap": false
                }
            }
            Или так:
            {
                "compilerOptions": {
                    "note": "Use legacy module format until migration is complete",
                    "todo": "Remove when done",
                    "module": "commonjs"
                }
            }


            1. justboris
              30.08.2018 02:52

              И всё это чудесным образом похерится как только кто-то откроет ваш конфиг а каком-нибудь визуальном редакторе JSON'а и сохранит его.

              Это проблема тулинга, а не комментариев как таковых


              Совершенно непонятно что мешает сдать так:

              С boolean еще более-менее удобно переключать, а если там enum? Вот в module могут быть 8 разных значений, переключаться между ними по памяти очень неудобно


              Или так:

              Ну это совсем костыли пошли. Нужно нормальное разделение: эта информация компьютерам, а остальная — людям.


              1. vintage
                30.08.2018 09:27
                -1

                Не нужно разделения. Вся информация должна легко читаться/писаться как компьютером, так и людьми. И если людям нужны комментарии, то машина должна иметь возможность как минимум их не терять, а как максимум — оперировать наравне с остальной информацией. Однако, модель данных JSON (словари, массивы и примитивы) не позволяет встраивать узлы с комментариями (и любой другой мета информацией, например, с позицией токена в исходном файле) в произвольное место дерева. Попытка решить эту проблему неизбежно приводит к чему-то типа DOM (списки типизированных узлов с детьми). JSON для сериализации DOM уже не подходит. XML подходит, но имеет кучу недостатков. Идеальный вариант — Tree, ибо разрабатывался специально для человекопонятного и машиночитаемого представления произвольных деревьев.


                1. mayorovp
                  30.08.2018 09:39

                  Вы про тот самый Tree, для которого невозможно построить DOM?..


                  1. vintage
                    30.08.2018 11:05

                    В смысле невозможно? Там после парсинга получаетстя АСТ, который по сути и есть DOM.


                    1. mayorovp
                      30.08.2018 11:30

                      Допустим я добавил в DOM значение "1\n2\n3", и сохранил в файл, а потом загрузил обратно. От нормального DOM я ожидаю что в нем будет нода с записанным значением, но Tree не позволяет реализовать это в принципе.


                      1. vintage
                        30.08.2018 21:22
                        -2

                        new $mol_tree({ value: '1\n2\n3' }).toString()
                        
                        "\1
                        \2
                        \3
                        "
                        
                        > $mol_tree.fromString( new $mol_tree({ value: '1\n2\n3' }) ).value
                        
                        "1
                        2
                        3"

                        Да, будет создано 4 ноды вместо одной, но это вполне прозрачно.


                        1. mayorovp
                          31.08.2018 06:22

                          Хорошо, а как тогда будет выглядеть массив [1,2,3]?


                          1. vintage
                            31.08.2018 06:43

                            Обычно массив получается как выборка:


                            const plugins = config.select( 'plugin' )

                            Но можно и модель JSON засунуть:


                            $mol_tree.fromJSON({ goals : [1,2,3] }).toString()
                            
                            "* goals /
                                1
                                2
                                3
                            "


                            1. mayorovp
                              31.08.2018 06:49

                              Э-э-э, что за знаки пуктуации? Вы когда про формат рассказывали обещали что массив будет выглядеть вот так:


                              goals
                                   \1
                                   \2
                                   \3


                              1. vintage
                                31.08.2018 07:24

                                Формат tree не знает ничего про массивы, словари, множества и другие типы данных. Представить массив в tree можно как вы описали, но чтобы собрать массив обратно нужно написать соответствующий код, например:


                                const goals = config.select( 'goals' , '' ).sub.map( node => Number( node.value ) )

                                Если мы хотим на входе и выходе иметь модель данных JSON, то нам нужно обозначить соответствующие типы данных специальными узлами, чтобы можно было автоматически конвертировать обратно в JSON. Поэтому в языке json.tree есть специальные токены: * для словарей и / для списков.


              1. khim
                30.08.2018 12:00

                Или так:

                Ну это совсем костыли пошли. Нужно нормальное разделение: эта информация компьютерам, а остальная — людям.
                Нет такого разделения. В подавляющем большинстве форматов, которые поддерживают комментарии через какое-то время появлются всякие «комментарии для doxygen»а, «директивы препроцессора» и прочая муть, которая явно не только читателям этого файла адресована.

                Лучше изначально комментарии вставлять в машинно-читаемом виде и в более-менее стандартизованном формате.


          1. Leopotam
            30.08.2018 10:14

            Это все можно провернуть с любым парсером JSON, выкусив комментарии после чтения, например, так: gist.github.com/Leopotam/6216f793982f39571546a606a3a68ea5


            1. justboris
              30.08.2018 10:35

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


              1. Leopotam
                30.08.2018 10:40

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


          1. Bronx
            31.08.2018 08:27

            С этим как раз особой беды нет. Если нет строгой валидации, то «закомментировать» элементы можно их переименованием:

            {
                "option": "active",
                "-option": "inactive",
                ...
            }
            


            Если валидатор не позволяет такое — можно просто удалять ненужные значения и полагаться на систему управления версиями.

            А вот если захочется многострочных текстов (или даже просто длинных, или текстов с большим количеством кавычек), то беда.


    1. mamont80
      30.08.2018 09:53

      Если добавить комментарии в стандарт JSON, тогда их представление нужно добавлять в парсер. А тогда он перестанет быть простым. В DOM представлении XML можно достать и прочитать комментарии. Отсюда ещё усложняющий нюанс — комментарии начнут использовать в качестве управляющих конструкций. Так например произошло с SQL в Oracle. Там комментарии используются для указания хинтов запросов, какой индекс использовать. Типа так: /*+ RULE */
      Для SQL это комментарий, а для СУБД нет. И мы получим уже навороченную конструкцию.
      Обратная совместимость, ещё один момент. Разный софт долго может работать и считать что общается на одном диалекте JSON, пока что-то пойдёт не так. Думаю другие диалекты JSON навсегда останутся сторонними инструментами. Есть ещё вагон недостатков JSON, если на то пошло. Например нормального представления даты-времени, бинарники, ссылки и т.п., аппетит приходит во время еды.


      1. apapacy
        30.08.2018 10:08

        www.w3.org/TR/xml/#sec-comments определяет что средства разбора могут но не должны обрабатывать комментарии.так что лучше на эту фразу не полагаться.
        www.w3.org/TR/xml/#sec-pi как раз для этого сразу предусмотрели управляющие инструкции


        1. khim
          30.08.2018 12:08

          www.w3.org/TR/xml/#sec-comments определяет что средства разбора могут но не должны обрабатывать комментарии.так что лучше на эту фразу не полагаться.

          А никто на неё и не полагается. Типичный разработчик начинает читать документацию только тогда, когда что-то ломается. Так что если парсер комментарии не выкидывает (а хотя бы каким-то из них придётся это делать, потому что иначе, понимаете ли проблемы тулинга возникнут), то их будут использовать. Вот совершенно независимо от того, что написано в документации.

          Собственно на эту тему есть всем известная статья — и если применить её к JSON, то станет понятно, что самая большая проблема с комментариями в JSON'е — это то, что существует много парсеров, которые принимают вроде-как-почти-но-не-совсем JSON-файлы с комментариями.


  1. scg
    29.08.2018 17:43
    +3

    Хм. Простой и элегантный, а количесво вопросов по нему на Stack Overflow растет. Парадокс.


    1. track13
      29.08.2018 18:38
      +4

      Там вопросы не по самому JSON, а по тому, как его использовать в том или ином фреймворке/языке/итд. К вопросу по QT ставят категорию C++, даже если спрашивают, как бэкграуд перекрасить, и C++ тут не при чём.


    1. Umpiro
      30.08.2018 14:03
      +1

      Что же тут парадоксального?
      Простой -> Популярный -> Количество вопросов на SO
      По пайтону недавно кто-то такую же зависимость обсуждал.


  1. stepik777
    29.08.2018 19:00
    +1

    К 2009 году активисты прекратили попытки написать вторую версию XHTML, когда стало ясно, что будущее за стандартом HTML5, который не требовал соответствия XML.

    Стандарт HTML5 разрешает два варианта представления — в виде HTML и в виде XML (так называемый XHTML5). Так что XHTML вполне себе жив и поддерживается всеми современными браузерами.


  1. ebt
    29.08.2018 22:08

    В защиту XML перед JSON могу сказать, что длинные и сложные многоуровневые иерархические структуры всё-таки гораздо комфортнее просматривать и править в XML, а не в JSON.


    1. Iqorek
      30.08.2018 02:53
      +1

      В обвинение XML могу сказать, нужно избегать всеми средствами длинных, сложных, многоуровневых, иерархических структур. А XML, даже простой, читать совершенно некомфортно, из-за большого информационного шума, на каждый байт данных, там миниум 2 байта метаданных, а в реальности все 10, которые в 99.99% не нужны.


      1. mayorovp
        30.08.2018 08:44

        И как же вы ее избежите, если предметная область длинная, сложная и многоуровневая? :-)


        1. Iqorek
          30.08.2018 11:16

          Тогда первое что нужно сделать, это избавиться от XML, потому что он добавляет длинны, сложности и уровни. Дальше универсального рецепта нет, по обстоятельствам.


          1. mayorovp
            30.08.2018 13:04

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


    1. DaylightIsBurning
      30.08.2018 11:35

      Не совсем понял, почему XML в таком случае будет комфортнее. Можно пример?


      1. ebt
        30.08.2018 13:03

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


        1. Chamie
          30.08.2018 13:47

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


          1. mayorovp
            30.08.2018 13:57

            Например, вот так:


            <element
                attr1="..."
                attr2="..."
                attr3="..."
            >
                <child1>...</child1>
                <child2>...</child2>
                <child3>...</child3>
            </element>


            1. Chamie
              30.08.2018 14:19

              …и в итоге у вас аттрибуты на том же уровне, что и дети, а следить приходится всё равно за (тадам!) закрывающей (угловой) скобкой. Точно так же, как в JSON.


              1. mayorovp
                30.08.2018 14:27

                А в чем проблема атрибутов и элементов на одном уровне?


                1. Chamie
                  30.08.2018 14:54
                  +1

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


                  1. MikailBag
                    30.08.2018 16:24

                    Так в JSON их просто нет!


                    1. khim
                      30.08.2018 21:55

                      И это хорошо.


  1. yurec_bond
    29.08.2018 23:46
    -1

    Сила XML в неймспейсах (namespace) — но их мало кто понимает

    Как формат для передачи данных, в обоих форматах (XML и JSON) не хватает ссылок (внутренних ссылок между объектами в документе)

    Читать JSON действительно легче. А вот писать ИМХО сложно и противно, в основном из-за запятых.

    P.S. Использовать JSON в качестве формата для конфигурационных файлов — смертный грех


    1. Iqorek
      30.08.2018 03:22

      Эти неймспейсы ещё больше замусоривают код. Спасибо, что мы от них избавились.
      Ссылки, за столько лет ни разу не было в них нужды, но тоже не проблема, например так:

      {
         "prop1": { 
            "prop11": "val1"
         },
         "prop2": "#ref://prop1/prop11" 
      }
      

      да после парсинга надо будет пробежаться по объекту и заменить #ref:// на ссылку на объект.
      Но лучше чтобы объекты были простые и плоские.
      Использовать JSON в качестве формата для конфигурационных файлов — смертный грех

      Если XML, уж лучше JSON, но после множества перепробованных форматов, я склоняюсь, что лучший формат конфигурации, это старый добрый ini, простой, лаконичный, читабельный и даже если где то нет для него парсера, можно самому написать в 3 строки, иногда еще короче.


    1. sand14
      30.08.2018 09:36

      > Сила XML в неймспейсах (namespace) — но их мало кто понимает

      В теории.

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

      Так же, как никто не обрабатывает нормально XML схему перед чтением.
      Суть в том, что XML это сложное решение, которое требует промышленного подхода в работе, и в эпоху скрама и аджайла с ним точно никто не будет работать нормально, к сожалению.
      Сделать поддержку какого-нибудь сложного XML-based формата или конфига за пару дней никто ж е даст — это ж чуть ли не Epic Story, за которую нужно делать продуктовые таски.


  1. apapacy
    30.08.2018 01:12
    +2

    Есть одно существеное преимущество котрое делает JSON удобнее чем XML, если использовать XML без описания схемы документа (а такой случай довольно часто встречается). У JSON есть способ задания массива значений который исключает многозначаность, которая писутсвует в XML.
    Сравним два документа

    <root>
       ...
        <users>
            <user><name>John</name></user>
        </users>
       ...
    </root>
    

    <root>
        ...
        <users>
            <user><name>John</name></user>
            <user><name>Joe</name></user>
        </users>
        ...
    </root>
    

    При разборе второго случая ясно что это будет массив
    $root['users']['user'][0]['name'] === 'John'
    А что с первым случаем? Парсер если нет заданной схемы не знает как разобрать документ. И в зависимости от опций может выдать результат
    $root['users']['user']['name'] === 'John'

    Или если задать в опциях что все единичные элементы считаются массивами
    $root['users'][0]['user'][0]['name'] === 'John'

    Но в этом случае даже там где подразумеваются всегда единричные элементы приходится все писать через [0].
    И еще ведь нельзя в XML задать чтобы было
    $root['users'][0]['name'] === 'John'

    Нужно обязательно вот это ['users']['user']
    Обмен документами ХМL без заданной схемы это не такой уж надуманный случай. Я напрпимер недавно интегрировался с очень популярной у нас системой обработки заказов клиентов (примем заказа, изготовление, доставка) где обмен шел по SOAP. Казалось бы, SOAP по опредеению идет только по зараннее заданной схеме. Но наш разработчик найдет способ. Да по SOAP шел обмен. Но в документе был описано ровно один строковый элемент с именем xml который собствено и нужно было разбирать. Пришлось для каждого такого ответа самому создавать описание схемы чтобы можно было без больших проблем сделать парсинг этог документа.
    Поэтому совсем не удивительно что для простых случаев JSON сейчсас превалирует.
    Еси говорить чего не хватает то я бы назвал тип даты. С числами также нет возможность задать целые числа и числа с фиксированной точкой (точностью).


    1. mayorovp
      30.08.2018 08:57

      Строковый элемент с именем xml? За такое руки отрывать надо, а не использовать эту ситуацию в качестве аргумента :-)


      Что же до неоднозначности разбора XML — тут все просто. Надо не заниматься десериализацией без схемы, а использовать XPath. В запросе /root/users/user[1]/name нет никакой неоднозначности.


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


      1. adeptoleg
        30.08.2018 09:08

        Никто не спорит просто для передачи информации XML слишком жырный. А вот как средство удобного хранения конфигов XML я думаю по цена качество идеален


        1. mayorovp
          30.08.2018 09:23

          Рассмотрим для примера вот такую страницу: https://portal.eaeunion.org/sites/odata/_layouts/15/Registry/Share/CardView.aspx?Code=P.TS.01&EntityId=646 (это случайная карточка из случайного реестра, не ищите в выборе реестра и карточки скрытых смыслов)


          Вы уверены, что запихнув все эти данные в JSON вы упростите передачу информации, а не усложните?


          1. apapacy
            30.08.2018 09:57

            Мы говорим в данном случае об xml без схемы. Если описать схему документа потом сериализовать в объект то конечный пользователь сервиса будет просто счастлив. Но если разбирать этот документ без схемы или ещё лучше запросами DOM или XPath то уверен с json проще.


            1. mayorovp
              30.08.2018 10:38

              Конечно же я говорю об XML со схемой! Любые сложные данные без схемы — это мусор, а не данные…


              1. khim
                30.08.2018 12:29

                А как насчёт реальности? Когда есть схема XML, есть данные — и эти данные схеме не очень-то соотвествуют? И нужные вам данные засунуты либо туда, где, по хорошему, должно лежать что-то другое, либо вообще в комментарии?

                Как показывает практика — XML-базы очень быстро превращаются именно в этот вариант.


                1. mayorovp
                  30.08.2018 12:48

                  Как показала практика — XML-база может годами оставаться в нормальном состоянии и ни во что не превращаться.

                  К примеру, если вы найдете XML-исходник для документа по ссылке выше — вы не найдете там никаких данных в комментариях или в нарушающем семантику тэге.


                  1. khim
                    30.08.2018 13:33

                    Хорошо если так. Но в моей практике — это происходит ровно до тех пор, пока в XML не приходится добавлять никаких новых сущностей. А в этом случае не только JSON, но и CSV хватает.

                    А вот если расширение требуется… То тут веселье и начинается.


                    1. mayorovp
                      30.08.2018 13:44

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


                      1. khim
                        30.08.2018 14:15

                        Добавление новых сущностей начинается с расширения схемы и ее согласования.
                        Это идеал, который я очень редко видел применяющимся на практике. Особенно если данные должны «протуннелировать» через несколько слоёв. Потому что в этом случае гораздо проще договорится, скажем, что альтернативные имена познаются, по прежнему, в тег , но отделяются там запятыми или пробелами или ещё как нибудь. Ну вспомните хотя бы про аттрибут «class» в XHTML!

                        Что значительно лучше чем JSON, где никому даже в голову не приходит использовать какую-то глупую схему и ее согласовывать, в результате чего о новой схеме все узнают по факту поломки взаимодействия, и хорошо еще если оно не на проде поломалось...
                        Опять-таки, из практики: поломка — это гораздо лучше, чем когда у вас всё «как бы работает»… но неправильно. И да, отсутствие схемы сразу автоматически означает, что её не нужно согласовывать, а также, при грамотном использовании, то, что если у
                        вас несколько потребителей, то про ваши расширения, которые касаются не всех, не нужно будет всем и сообщать.


                        1. mayorovp
                          30.08.2018 14:38

                          А вот как раз в таких случаях и нужны пространства имен на которые тут уже жаловались. В общую схему добавляется <xs:any namespace="..." processContents="lax" /> и все. Кому эти данные предназначены, с тем согласовывается дополнительная схема, а остальные эти элементы игнорируют.


                          1. khim
                            30.08.2018 22:14

                            Опять двадцать пять. Вы опять исходите из идаелистичной картинки, где люди читают и пишут спеки, доки, и соблюдают то, что в них написано.

                            Но это же не так. Посмотрите на мои примеры, на пример с которого всё началось. Да, блин, посмотрите на OOXML — это, между прочим, международный стандарт. 6546 страниц документации. А описание принтера, с которым этот документ свёрстан — это, я извиняюсь, CDATA. Почти как тот «строковый элемент с именем xml», с которого всё началось.

                            Думаете это мелкая деталь реализации, которая мало на что влияет? Ага, я вам щаз губозакатывательную машинку подарю: вся вёрстка в MS Office завязана на характеристики конкретного принтера, для которого документ верстается. Вся. Вплоть до того, что если вы верстаете книжку под какой-нибудь матричник 360dpi, а потом пытаетесь послать её в типографию, чтобы там её распечатали на устройстве с 300dpi или 1200dpi, то зачастую сможете обнаружить что у вас в книжке стало другое количество страниц!

                            А вы говорите — сограсовывание схем и пространства имён… Ага. Щаз.

                            Может где-нибудь в NASA ваши идеи и будут работать, но в других местах… 90% разработчиков на поддрежку пространств имён просто забьют. А 90% из оставшихся реализуют поддержку — но сделают это с ошибками. Потому что док они не читают, ничего ни с чем не согласовывают, а код пишут путём дёрганья ответов на случайные вопросы на StackOverflow.

                            Это не то, что стоит обсуждать и не то, с чем стоит бороться — это просто данность. За написание программ и закрытие «тасков» платят, а за согласование «схемы» — нет. Всё дальнейшее из этого следует.


                            1. mayorovp
                              31.08.2018 06:28

                              За согласование схемы тоже платят. Архитекторам и системным аналитикам.


          1. khim
            30.08.2018 12:27

            Вы уверены, что запихнув все эти данные в JSON вы упростите передачу информации, а не усложните?
            Уверен. Именно потому что данные будут иногда не лезть в оговоренный способ представления — и его придётся менять.

            Вместо того, чтобы впихивать круглую палку в квадратное отверстие «очень сильным программистом», которое потом нужно будет расхлёбывать на стороне парсера.


        1. MacIn
          30.08.2018 13:29

          Смотря какие задачи… гляда на нынешние свои, могу с апломбом заявить, что INI файлы как средство для удобного хранения конфигов — юбер аллес.


      1. apapacy
        30.08.2018 09:52

        На самом деле это продукт используют наверное половина если не 90% служб по дизготовлению и доставке пиццы, суши и т.п. При их доходах можно было бы сделать все нормально. Тут и аргумент не нужен. Или так или никак. Кстати это не единственный в моей практике случай. Правда в других случаях я мог теоретически повлиять на ситуацию. Но не сделал этого т.к. понимал что сроки предоставления мне служб soap будут сорваны.


      1. khim
        30.08.2018 12:23

        Строковый элемент с именем xml? За такое руки отрывать надо, а не использовать эту ситуацию в качестве аргумента :-)
        Вот спека. Расскажите, кому и когда вы будете отрывать руки. Вот вам ещё парочка (AArch32 и AArch64). Я работал со всеми тремя за последний год. Все ужасы, про которые тут говорится — там имеюются во всей красе.

        Возьмём первую «машинночитаемую» спеку, чтоб не быть голословными.

        В том, что для простых случаев JSON подходит лучше — соглашусь, но не каждый случай простой.
        Каждый. Попытки использовать вышеописанные спеки напрямую — приводили к тому, что чуть не под каждую новую версию приходилось инструменты «допиливать». После того, как написали конвертор из XML в JSON — допиливать приходится только его. Иногда приходится допиливать и клиенты, но это всегда проще сделать, чем в случае с JSON'ом.

        Что же до неоднозначности разбора XML — тут все просто. Надо не заниматься десериализацией без схемы, а использовать XPath. В запросе /root/users/user[1]/name нет никакой неоднозначности.
        Расскажите, пожалуйста, каким XPath-запросом вы будете получать тип поля computeWorkGroupSize из его следующего описания:
        <member><type>uint32_t</type> <name>computeWorkGroupSize</name>[3]</member>
        На всякий случай замечу, что речь идёт о типа uint32_t[3]

        Заранее спасибо за ваше умение в XPath-фу.


        1. mayorovp
          30.08.2018 12:57

          Ничего сложного: //member/name[.="computeWorkGroupSize"]/following-sibling::text()[1].


          Ну или вот так тоже можно: //member[name="computeWorkGroupSize"]/text()


          1. khim
            30.08.2018 13:29

            Я боюсь, что вы так захватите вместе с типом ещё и имя. А если там окажется в промежутке ещё и (посмотрите на ссылку), то он тоже будет захвачен.

            А для того, чтобы сгенерировать API — нужно-таки вычленить именно uint32_t[3] — у этого элемента именно такой тип.


            1. mayorovp
              30.08.2018 13:39

              Нет, так я захватываю [3] и только его (второй вариант захватывает еще и пробел).
              Тип захватывается вот так: //member[name="computeWorkGroupSize"]/type, я думал что это очевидно.


              1. khim
                30.08.2018 14:22

                То, что тип можно захватить отдельно и текст [3] можно захватить отдельно — это я знаю. Проблема в том, что в vk.xml тип описывается как в C: базовый тип помечен как type, но при этом всякие скобочки и звёздочки никак не помечены. И могут идти и до имени и после.

                Проще всего взять тег «member», выбросить из него теги «comment» и «name» и объявить всё оставшееся типом. Но как это сделать на XPath — я не знаю…


                1. mayorovp
                  30.08.2018 14:50

                  Тогда так:


                  //member[name="computeWorkGroupSize"]/node()[local-name() != 'name' and local-name() != 'comment']

                  Или вот так:


                  //member[name="computeWorkGroupSize"]/node()[not(self::name | self::comment)]


                  1. TerraV
                    30.08.2018 15:59

                    И как вам самому такое, нравится? Мне категорически нет (даже если оно делает то что нужно, в чем лично у меня большие сомнения).


                    1. mayorovp
                      30.08.2018 16:11

                      А в чем проблемы этого запроса, за исключением того что это однострочник? Если вам не нравятся однострочники — ну пишите в несколько строчек! Применительно к xpath — делайте несколько запросов.


                      Или вот тот же самый запрос на Linq 4 Xml:


                      from member in doc.Descendants("member")
                      where (string)member.Element("name") == "computeWorkGroupSize"
                      from node in member.Nodes()
                      where node.Name != "name" && node.Name != "comment"
                      select node


                1. mayorovp
                  30.08.2018 16:36

                  Кстати, вот еще что мне подумалось. Если по-смотреть на вашу спеку внимательнее, то видно что она писалась ровно с одной целью — чтобы по ней было удобно генерировать человекочитаемую документацию.


                  В частности, содержимое member на самом деле — просто неструктурированная строка uint32_t computeWorkGroupSize[3], в которой идентификатор uint32_t выделен как ссылка на тип, а computeWorkGroupSize — как имя.


                  В том же JSON такое просто не поместится. И будет либо что-то типа вот такого:


                  [
                      {token: "uint32_t", type: "type"},
                      " ",
                      {token: "computeWorkGroupSize", type: "name"},
                      "[3]"
                  ]

                  Либо будет вот такое: \type{uint32_t} \name{computeWorkGroupSize}[3]


                  И это в лучшем случае — в худшем случае в json могут и кусок html-разметки запихать, как я уже много раз видел.


                  Будет ли удобно вырезать в таких форматах имя и комментарий? Почему-то мне кажется, что нет. Так что проблема этой спеки — вовсе не в формате XML.


                  1. khim
                    30.08.2018 22:44

                    Если по-смотреть на вашу спеку внимательнее, то видно что она писалась ровно с одной целью — чтобы по ней было удобно генерировать человекочитаемую документацию.
                    А вы самый первый «comment» в ней прочитали, нет?

                    Цитирую:
                    This file, vk.xml, is the Vulkan API Registry. It is a critically important and normative part of the Vulkan Specification, including a canonical machine-readable definition of the API
                    Увы — но это «canonical machine-readable definition of the API». Которым пользуются разработчики GPU, операционок и прочего для того, чтобы верифицировать данные… А вовсе не «заготовка книжки» как вам показалось…

                    В том же JSON такое просто не поместится.
                    И это прекрасно, великолепно, замечательно! Это и есть основное и самое главное достоинство JSON'а!

                    И будет либо что-то типа вот такого:

                    [
                        {token: "uint32_t", type: "type"},
                        " ",
                        {token: "computeWorkGroupSize", type: "name"},
                        "[3]"
                    ]
                    Зачем, почему, отчего? После конвертации там у нас что-то типа такого:
                    "members" : [
                    ...
                    {
                         "name" : "maxComputeWorkGroupSize",
                         "type" : "uint32_t[3]"
                    }
                    ...
                    ]
                    Всё просто, понятно, и легкоиспользуемо. Осовенно если учесть, что в другом месте там есть ещё и массив «types», примерно такого плана:
                    "types" : {
                    ...
                            "uint32_t[3]" : {
                                "kind" : "array",
                                "element_type" : "uint32_t"
                            },
                    ...
                    }
                    
                    И это в лучшем случае — в худшем случае в json могут и кусок html-разметки запихать, как я уже много раз видел.
                    Могут. Но шансов на то, что это случится — гораздо меньше, чем если попросить породить XML. И это легко очень быстро заметить. Ну просто появление первого же символа "<" иди ">" приведёт к вопросам «что за <крепкое ругательство> здесь написано и когда это исправят»? В случае же с XML — оно живёт и здравствует уже который год…

                    Так что проблема этой спеки — вовсе не в формате XML.
                    Нет, её проблема — в том, что «ужас, летящий на крыльях ночи» (и порождённый, скорее всего, каким-нибудь perl'овым скриптом из заголовочных файлов) не выглядит при беглом взгляде как ужас.

                    Я где-то давно как-то увидел фразу, которая показывает главное и основное преимущество JSON перед XML: «great APIs are easy to use, greatest APIs are hard to abuse».

                    Так вот XML — это «great API», а JSON — это «greatest API». Именно, блин, потому, что ужас засунутый в JSON — таки выглядит как ужас (если у вас в «canonical machine-readable definition of the API» появляются теги «token», или, прости госсподи, HTML — то это легко заметить и понять что это — неправильно). А вот ужас засунутый в XML — выглядит неотличимо он нормального XML'я, который можно спокойно распарсить без применения бесконечного количества костылей…


                    1. mayorovp
                      31.08.2018 06:31

                      Зачем, почему, отчего? После конвертации там у нас что-то типа такого [...]

                      Так то у вас. Потому что у вас была задача сделать и правда машиночитаемую документацию. А вот перед разработчиками обсуждаемого документа такая задача если и стояла — они ее просто не поняли.


                      1. khim
                        31.08.2018 23:24
                        +1

                        Они её прекрасно поняли.

                        Понимаете, перед разработчиками этой спеки (а если вы хотя бы откроете Википедию, то увидите, что собственно выпуск подобных файлов — это то, за что они деньги получают) стояла задача: «к часу X иметь машинно-читаемую спеку». А у разработчиков GPU стояла другая задача: «у часу Y выпустить чип, с поддержкой спеки, а к часу Z — драйвера». А у разработчиков Андроида и MoltenVK задача была «сделать так, чтобы в час T можно было запускать на устройствах программы, соотвествуюшие спеке». И так далее. Потому что оно должно поступить в продажу либо в августе (если мы целимся в «back-to-school»), либо в конце ноября (если мы хотим дать это Санта-Клаусу), либо в январе-феврале (если мы со школами работаем) и так далее. Если мы совали сроки не на день-два, а скажем, на месяц — то мы влетели в миллиардные убытки…

                        И, что характерно, все более-менее со всеми своими задачами справились — именно потому что у них не было важных «Архитекторов и системных аналитиков», которые могли бы устроить многомесячные «согласования схемы» и сорвать к чертям собачьим все сроки. Вместо этого на всех уровнях было прикручено столько и таких костылей, сколько было нужно для того, чтобы вот это вот всё как-то заработало…

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

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

                        А без спеки и её согласования, как вы сами признаёте, шансов получить что-то вменяемое от XML — меньше, чем от JSON'а…


                        1. mayorovp
                          01.09.2018 09:03

                          Понимаете в чем дело, если бы передо мной стояла задача сделать XML-спеку для того чтобы из нее можно было генерировать человекочитаемую документацию для Си или С++ — я бы тоже, после некоторых раздумий, выбрал именно такою схему. А если бы передо мной стояла задача сделать машиночитаемую документацию — я бы выбрал совсем другую схему, причем думал бы куда меньше, потому что машиночитаемые форматы проще.

                          Именно поэтому мне кажется, что реально решаемая этой спекой задача отличается от заявленной.


                          1. vintage
                            01.09.2018 09:46

                            Прелесть XML спек в том, что их можно писать машиночитаемо, но тут же к ним приложить XSLT странсформацию, которая создаст человекочитаемое представление. Пример: nin-jin.github.io/harp/api=1


                            1. mayorovp
                              01.09.2018 13:24

                              Вот только конкретно эту спеку явно писали одновременно с XSLT и для нужд именно этой XSLT, а не для чего-то еще.


                              1. khim
                                01.09.2018 14:07

                                Да не обрабатывается эта спека никаким XSLT! Зачем думать и гадать? Всё ж открыто! Там и скрипты, которые спеку читают, есть и Relax NG schema и прочее. Никакого XSLT нигде нет — но сам документ… вот такой.

                                Если вы предположите, что и схему и документ породили люди, которые имели больше опыта работы с написанием документации, чем с написанием кода и потому понимали нужды XSLT лучше, чем нужны программистов на C/C++… то вы будете правы.

                                Но, тем не менее, результат — таков, каким вы его видите.

                                И не надо говорить про то, что это результат работы студентов: Khronos Group существует с 2000го года, сколько времени существует nVidia, AMD (ну пусть ATI… тут это релевантнее) — вы тоже примерно представляете.

                                То есть нет — это не «малобюджетный проект, которым занимались делетанты». Это — то, что вы реально (а не в ваших мечтах) получаете от XML в индустрии.

                                Great APIs are easy to use, greatest APIs are hard to abuse — так вот вторую часть XML проваливает с треском… его очень-очень «easy to abuse»…


    1. adeptoleg
      30.08.2018 09:05

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


  1. Alter2
    30.08.2018 10:55

    Представьте себе мир, в котором у HTML-документов и ответов API в точности одинаковая структура. В таком мире JSON, возможно, не стал бы таким популярным, как сегодня.

    А ведь JSON-подобный HTML — неплохая идея для современных сайтов, где большие тексты уже не особо распространены.


    1. justboris
      30.08.2018 11:01

      Вы не поверите, но кто-то уже так делает: en.bem.info/platform/bemjson


  1. akurilov
    30.08.2018 11:11

    Имхо, не хватает вспомогательных стандартизованных технологий наподобие XSLT, XQuery, XPath. Но если сравнивать json и yaml, то последний всё-таки предпочтительнее, т.к. комментарии есть и меньше ненужной избыточности


  1. apapacy
    30.08.2018 12:11

    habr.com/company/sberbank/blog/421693 как будто специально по теме почему не всегда xml делает разработку проще.


  1. Geos87
    30.08.2018 13:07
    +1

    по-моему, единственная причина почему JSON победил — это то, что браузеры так и не реализовали нормальную поддержку XML/XPath. А JSON по умолчанию был столь простой что JSON2.js, по-моему, 200 строк в неминимизированном виде. Если бы в браузерах была поддержка XML на том же уровне что System.Xml.* в .NET, JSON вряд ли был так нужен.


  1. MacIn
    30.08.2018 13:26

    Судя по графику, мы имеем дело с непрерывным ростом CSV.


  1. muhaa
    30.08.2018 13:39

    Шок! Стулья захватили мир! Это было поразительное изобретение, сделанное… в… году. Впервые четырехногий стул изготовили… Они столкнулись с массой трудностей, которые героически преодолели. Стульев в мире становится все больше (вот вам график) хотя некоторые все еще предпочитают табуретки, скамейки или кресла на колесиках.
    Т.е. берем какие-нибудь простейшие и очевидные решения, придаем им статус прорывных технологий и пишем громкую статью.


  1. springimport
    30.08.2018 15:59

    Очень легко начать пользоваться json когда нужно просто:

    { "title": "Post title", "body": "Post Body" }


    Однако в очередной раз не вышло серебряной пули. Уже начали появляться инструменты типа Swagger. Вопрос времени когда введут схемы и нэймспейсы.