Pull to refresh

Comments 138

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

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

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

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

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

Просто потому что все понимают — JSON есть JSON, а начни «улучшать» и конца-края не будет.
Сравнение на графике какое-то безумное) могли бы ещё добавить HTML, plain text, xlsx, blob'ы. Почему бы и нет? Могут ведь! Главное чтобы JSON был выше всех
Потому что задача статьи — «Шок! Видео! Трепет! Скандалы!»
«Редактор GT» — оно такое. Это их работа.

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

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


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


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

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

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

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

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

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

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


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


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

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

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


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


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

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

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

Пару примеров, где комментарии в 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-синтаксисе.

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

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

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

Я в свое время достаточно наредактировался файлов 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% состоит из воды.

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


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


    <plugin groupId="org.apache.maven.plugins" artifactId="maven-source-plugin">
        <execution id="attach-sources">
            <goal>jar</goal>
        </execution>
    </plugin>
Это будет работать до тех пор пока у вас один plugin, один execution и один goal (ну или если под execution не может лежать ничего кроме goal, под plugin — ничего кроме execution и т.д.).

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


<plugin ...>
    <execution>...</execution>
    <execution>...</execution>
    <execution>...</execution>
    <execution>...</execution>
    <foo>...</foo>
    <foo>...</foo>
    <bar>...</bar>
</plugin>
А теперь уговорите сообщество перейти на этот формат. Про что вам собственно и говорят. XML это или мысль в камне или аццкая боль переделки.
Переделать как раз не проблема — в данном случае идет речь о xml покрытом хорошей xsd схемой, сконвертировать один формат в другой несложно каким-нибудь xslt.
А вы тогда уговорите сообщество перейти на JSON. Про что я собственно и говорю, что проблема не в XML, а в выбранной схеме.
Оно будет работать в том смысле, что распарсится, но оно не очень будет работать с точки зрения читаемости. Вот у 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>

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


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


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

Что же до формата реальных конфигов — я все еще не верю что от слепого преобразования в JSON они выиграют в читаемости.
Так ведь с этим никто вроде и не спорит. У json свои проблемы, у xml — свои.
Да нет, в этой ветке как раз сравнивают форматы JSON и XML применительно к задаче написания конфигов на примере конфигов Typescript Compiler и Maven, против чего я и возражаю.
Ну если для «человекочитаемого» формата нужен специальный редактор, чтобы его было удобно читать, то что-то не так с этим форматом.
Это проблема многословности схемы самого Maven, а не формата (это как раз рядом обсуждают). И плагин решает именно эту проблему, и не какую-то ещё.

Хотя Вам уже ответили, но вот 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 версия больше нравится.

Моя версия:

{
  "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-м названии свойства для каждого объекта (Id). Зато сломали мозг пользователям, которые без вашего объяснения не будут знать, как править конфиг, а так же заставив разработчиков написать вручную десериализаторы для чтения таких конфигов т.к. я думаю ни в Java (для которой собственно и был пример приведён), ни в C#, ни в любом другом языке по умолчанию сериализаторы не будут знать о ваших оптимизациях.
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>

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

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


plugin
    groupId \org.apache.maven.plugins
    artifactId \maven-source-plugin
    execution
        id \attach-sources
        goal \jar
Давно уже заменён на бэкслеш, чтобы не вводить в заблуждение. Это префикс сырых данных, а не разделитель ключа и значения.
Вот в этом и (еще одна) проблема языка tree — вы его меняете как пожелаете и держите изменения синтаксиса в секрете.

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

Если вы используете JS стек технологий, то напишите конфигурацию в JS файле. К примеру:
// file settings.js
const settings = {
  host: 'localhost',
  port: 3000
};

export default Object.freeze(settings);


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

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


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

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

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

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

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

Совершенно непонятно что мешает сдать так:
{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": false,
        "sourceMap": false
    }
}
Или так:
{
    "compilerOptions": {
        "note": "Use legacy module format until migration is complete",
        "todo": "Remove when done",
        "module": "commonjs"
    }
}
И всё это чудесным образом похерится как только кто-то откроет ваш конфиг а каком-нибудь визуальном редакторе JSON'а и сохранит его.

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


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

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


Или так:

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

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

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

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

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

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,2,3]?

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


const plugins = config.select( 'plugin' )

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


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

"* goals /
    1
    2
    3
"

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


goals
     \1
     \2
     \3

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


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

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

Или так:

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

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

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

А можно изобрести телепатический передатчик и слать данные напрямую пользователю в мозг. Нужно соизмерять трудоемкость решения, выкусывание лишней информации одной регуляркой гораздо проще, чем куча кода по генерации данных руками. Ну и самое главное — это сохранит совместимость со всеми реализациями парсера, что важнее, чем удобство применения формата в одном конкретном случае.
С этим как раз особой беды нет. Если нет строгой валидации, то «закомментировать» элементы можно их переименованием:
{
    "option": "active",
    "-option": "inactive",
    ...
}


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

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

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

Собственно на эту тему есть всем известная статья — и если применить её к JSON, то станет понятно, что самая большая проблема с комментариями в JSON'е — это то, что существует много парсеров, которые принимают вроде-как-почти-но-не-совсем JSON-файлы с комментариями.
UFO just landed and posted this here
Там вопросы не по самому JSON, а по тому, как его использовать в том или ином фреймворке/языке/итд. К вопросу по QT ставят категорию C++, даже если спрашивают, как бэкграуд перекрасить, и C++ тут не при чём.
Что же тут парадоксального?
Простой -> Популярный -> Количество вопросов на SO
По пайтону недавно кто-то такую же зависимость обсуждал.
UFO just landed and posted this here

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

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

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

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

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

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

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

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


<element
    attr1="..."
    attr2="..."
    attr3="..."
>
    <child1>...</child1>
    <child2>...</child2>
    <child3>...</child3>
</element>
…и в итоге у вас аттрибуты на том же уровне, что и дети, а следить приходится всё равно за (тадам!) закрывающей (угловой) скобкой. Точно так же, как в JSON.
А в чем проблема атрибутов и элементов на одном уровне?
В том, что это разного рода сущности с разными отношениями к родительскому элементу, и отступы разбирать их не помогают, в отличие от JSON.
Сила XML в неймспейсах (namespace) — но их мало кто понимает

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

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

P.S. Использовать JSON в качестве формата для конфигурационных файлов — смертный грех
Эти неймспейсы ещё больше замусоривают код. Спасибо, что мы от них избавились.
Ссылки, за столько лет ни разу не было в них нужды, но тоже не проблема, например так:
{
   "prop1": { 
      "prop11": "val1"
   },
   "prop2": "#ref://prop1/prop11" 
}

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

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

В теории.

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

Так же, как никто не обрабатывает нормально XML схему перед чтением.
Суть в том, что XML это сложное решение, которое требует промышленного подхода в работе, и в эпоху скрама и аджайла с ним точно никто не будет работать нормально, к сожалению.
Сделать поддержку какого-нибудь сложного XML-based формата или конфига за пару дней никто ж е даст — это ж чуть ли не Epic Story, за которую нужно делать продуктовые таски.
Есть одно существеное преимущество котрое делает 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 сейчсас превалирует.
Еси говорить чего не хватает то я бы назвал тип даты. С числами также нет возможность задать целые числа и числа с фиксированной точкой (точностью).

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


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


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

UFO just landed and posted this here

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


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

Мы говорим в данном случае об xml без схемы. Если описать схему документа потом сериализовать в объект то конечный пользователь сервиса будет просто счастлив. Но если разбирать этот документ без схемы или ещё лучше запросами DOM или XPath то уверен с json проще.
Конечно же я говорю об XML со схемой! Любые сложные данные без схемы — это мусор, а не данные…
А как насчёт реальности? Когда есть схема XML, есть данные — и эти данные схеме не очень-то соотвествуют? И нужные вам данные засунуты либо туда, где, по хорошему, должно лежать что-то другое, либо вообще в комментарии?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Вместо того, чтобы впихивать круглую палку в квадратное отверстие «очень сильным программистом», которое потом нужно будет расхлёбывать на стороне парсера.
Смотря какие задачи… гляда на нынешние свои, могу с апломбом заявить, что INI файлы как средство для удобного хранения конфигов — юбер аллес.
На самом деле это продукт используют наверное половина если не 90% служб по дизготовлению и доставке пиццы, суши и т.п. При их доходах можно было бы сделать все нормально. Тут и аргумент не нужен. Или так или никак. Кстати это не единственный в моей практике случай. Правда в других случаях я мог теоретически повлиять на ситуацию. Но не сделал этого т.к. понимал что сроки предоставления мне служб soap будут сорваны.
Строковый элемент с именем 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-фу.

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


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

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

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

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

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

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

Тогда так:


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

Или вот так:


//member[name="computeWorkGroupSize"]/node()[not(self::name | self::comment)]
И как вам самому такое, нравится? Мне категорически нет (даже если оно делает то что нужно, в чем лично у меня большие сомнения).

А в чем проблемы этого запроса, за исключением того что это однострочник? Если вам не нравятся однострочники — ну пишите в несколько строчек! Применительно к 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

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


В частности, содержимое 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.

Если по-смотреть на вашу спеку внимательнее, то видно что она писалась ровно с одной целью — чтобы по ней было удобно генерировать человекочитаемую документацию.
А вы самый первый «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'я, который можно спокойно распарсить без применения бесконечного количества костылей…
Зачем, почему, отчего? После конвертации там у нас что-то типа такого [...]

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

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

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

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

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

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

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

Именно поэтому мне кажется, что реально решаемая этой спекой задача отличается от заявленной.
Прелесть XML спек в том, что их можно писать машиночитаемо, но тут же к ним приложить XSLT странсформацию, которая создаст человекочитаемое представление. Пример: nin-jin.github.io/harp/api=1
Вот только конкретно эту спеку явно писали одновременно с XSLT и для нужд именно этой XSLT, а не для чего-то еще.
Да не обрабатывается эта спека никаким 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»…
UFO just landed and posted this here

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


$my_app $mol_view
    full_title <= title \Common content
    short_title <= title
    long_title <= title
UFO just landed and posted this here
UFO just landed and posted this here
Представьте себе мир, в котором у HTML-документов и ответов API в точности одинаковая структура. В таком мире JSON, возможно, не стал бы таким популярным, как сегодня.

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

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

по-моему, единственная причина почему JSON победил — это то, что браузеры так и не реализовали нормальную поддержку XML/XPath. А JSON по умолчанию был столь простой что JSON2.js, по-моему, 200 строк в неминимизированном виде. Если бы в браузерах была поддержка XML на том же уровне что System.Xml.* в .NET, JSON вряд ли был так нужен.
Судя по графику, мы имеем дело с непрерывным ростом CSV.
Шок! Стулья захватили мир! Это было поразительное изобретение, сделанное… в… году. Впервые четырехногий стул изготовили… Они столкнулись с массой трудностей, которые героически преодолели. Стульев в мире становится все больше (вот вам график) хотя некоторые все еще предпочитают табуретки, скамейки или кресла на колесиках.
Т.е. берем какие-нибудь простейшие и очевидные решения, придаем им статус прорывных технологий и пишем громкую статью.
Очень легко начать пользоваться json когда нужно просто:
{ "title": "Post title", "body": "Post Body" }


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

Articles