Comments 138
Всё ещё впереди. Поначалу Flash тоже был простой штукой и позволял просто делать милые анимации. Потом люди сказали — а давайте все улучшим, правда, придётся немного усложнить. И усложнили так, что Flash издох, не оставив альтернатив — слишком навороченной и сделай и сложной получилась поделка. Удержатся ли люди от "улучшения и усложнения" — только со временем увидим.
Просто потому что все понимают — JSON есть JSON, а начни «улучшать» и конца-края не будет.
(что, однако, не спасает от ошибок при очередных изменениях формата взаимодействия между системами)
Уже "придумали" суперсет для JSON, так называемый JSON5.
Разумеется, станет ли это распространённым или нет — вопрос, но самые "болезненные" недостатки обозначены — trailing commas, отсутствие ссылок и комментариев.
Мне кажется — что нет, не станет. Проще использовать HCL [для людей], который полностью конвертируем в JSON [для машин и людей].
Спросите себя: если комментарий, который вы хотите прибавить к данным, настолько неважен, что его никто-никто и никогда не должен видеть — то зачем он вам? А если комментарий всё-таки может быть полезен для обработки (пусть иногда) — то что мешает его сделать отдельным полем 'notes', который большинство пользователей будет игнорировать?
Ссылки, также, проблема: если вам где-то нужна ссылка, то заведите ЯВНОЕ поле URL и обрабатывайте его ЯВНО. Не создавайте пользователям странных и неожиданных обращений в сеть там, где их быть не должно.
На самом деле бы из JSON'а парочку вещей бы выкинул ещё… Но он и в текущем виде достаточно прост — ради совместимости можно потерпеть. Но добавлять туда точно ничего не нужно.
Спросите себя: если комментарий, который вы хотите прибавить к данным, настолько неважен, что его никто-никто и никогда не должен видеть — то зачем он вам? А если комментарий всё-таки может быть полезен для обработки (пусть иногда) — то что мешает его сделать отдельным полем 'notes', который большинство пользователей будет игнорировать?
Ну например если есть задача сделать строгую схему данных, в которой запрещены опциональные свойства.
Для валидации ведь есть, как минимум, JSON Schema.
Если этого требует какая-то частная задача — можно попотеть и написать/поискать валидатор.
От того, что вы добавите строгую схему данных в условном JSON 2.0 и запретите опциональные свойства, конечные потребители не станут следовать этим правилам ввиду того, что уже есть тонны реализаций каноничного JSON, и ни в одночасье, ни в обозримой перспективе они не перейдут на новый стандарт, потому что "работает — не трожь".
Тем более, что немало реализаций поддерживают де-/сериализацию JSON с учётом требований, о которых вы говорите, правда, не на уровне спецификаций JSON, а на стороне библиотеки.
Спросите себя: если комментарий, который вы хотите прибавить к данным, настолько неважен, что его никто-никто и никогда не должен видеть — то зачем он вам?
JSON — уже далеко не только формат обмена данными между машиной-и-машиной, это ещё и способ описания конфигураций и часто применяется как файл профилей или файл настроек (хотя эта сфера постепенно вытесняется YAML).
Комментарии нужны, если JSON будет просматриваться, редактироваться и адаптироваться людьми под какие-то свои нужды.
Ссылки, также, проблема: если вам где-то нужна ссылка, то заведите ЯВНОЕ поле URL и обрабатывайте его ЯВНО. Не создавайте пользователям странных и неожиданных обращений в сеть там, где их быть не должно.
Речь не про URL, вообще не об этом. Речь про возможность сослаться на другие переменные (параметры) или шаблонизировать (аналогии — надстройки над CSS).
Пару примеров, где комментарии в 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-синтаксисе.
Честно говоря, это похоже на ситуацию, когда
А вот в конфигурационных файлах нужно комментировать, почему настроено именно так, а не иначе. В каком формате вы обычно пишете конфигурацию?
Я в свое время достаточно наредактировался файлов 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>...</execution>
<execution>...</execution>
<execution>...</execution>
<execution>...</execution>
<foo>...</foo>
<foo>...</foo>
<bar>...</bar>
</plugin>
И вы же понимаете что то что вы написали со временем выродится в
<plugin ...>
<execution>...</execution>
<foo>...</foo>
<execution>...</execution>
<bar>...</bar>
<bar>...</bar>
<foo>...</foo>
<execution>...</execution>
<execution>...</execution>
</plugin>
Да, я это понимаю. И считаю что нужно сознательно дать возможность пишущему конфиг писать элементы в том порядке в котором ему будет удобнее.
Но если вы считаете по-другому — ничто не мешает и потребовать строгого порядка элементов, в XSD есть все инструменты для этого.
Что же до формата реальных конфигов — я все еще не верю что от слепого преобразования в JSON они выиграют в удобочитаемости.
Что же до формата реальных конфигов — я все еще не верю что от слепого преобразования в JSON они выиграют в читаемости.Так ведь с этим никто вроде и не спорит. У json свои проблемы, у xml — свои.
Хотя Вам уже ответили, но вот 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).
Зато сломали мозг пользователям, которые без вашего объяснения не будут знать, как править конфигОни будут руководствуясь правилом: 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
Не было никакого секрета. А как показало обсуждение без данного изменения у формата нет никаких шансов обрести популярность.
// 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 все равно останется сложным и неудобным форматом.
Совершенно непонятно что мешает сдать так:
{
"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",
...
}
Если валидатор не позволяет такое — можно просто удалять ненужные значения и полагаться на систему управления версиями.
А вот если захочется многострочных текстов (или даже просто длинных, или текстов с большим количеством кавычек), то беда.
Для SQL это комментарий, а для СУБД нет. И мы получим уже навороченную конструкцию.
Обратная совместимость, ещё один момент. Разный софт долго может работать и считать что общается на одном диалекте JSON, пока что-то пойдёт не так. Думаю другие диалекты JSON навсегда останутся сторонними инструментами. Есть ещё вагон недостатков JSON, если на то пошло. Например нормального представления даты-времени, бинарники, ссылки и т.п., аппетит приходит во время еды.
www.w3.org/TR/xml/#sec-pi как раз для этого сразу предусмотрели управляющие инструкции
www.w3.org/TR/xml/#sec-comments определяет что средства разбора могут но не должны обрабатывать комментарии.так что лучше на эту фразу не полагаться.
А никто на неё и не полагается. Типичный разработчик начинает читать документацию только тогда, когда что-то ломается. Так что если парсер комментарии не выкидывает (а хотя бы каким-то из них придётся это делать, потому что иначе, понимаете ли проблемы тулинга возникнут), то их будут использовать. Вот совершенно независимо от того, что написано в документации.
Собственно на эту тему есть всем известная статья — и если применить её к JSON, то станет понятно, что самая большая проблема с комментариями в JSON'е — это то, что существует много парсеров, которые принимают вроде-как-почти-но-не-совсем JSON-файлы с комментариями.
Простой -> Популярный -> Количество вопросов на SO
По пайтону недавно кто-то такую же зависимость обсуждал.
В защиту XML перед JSON могу сказать, что длинные и сложные многоуровневые иерархические структуры всё-таки гораздо комфортнее просматривать и править в XML, а не в JSON.
В обвинение XML могу сказать, нужно избегать всеми средствами длинных, сложных, многоуровневых, иерархических структур. А XML, даже простой, читать совершенно некомфортно, из-за большого информационного шума, на каждый байт данных, там миниум 2 байта метаданных, а в реальности все 10, которые в 99.99% не нужны.
В JSON уровни вложенности задаются с помощью квадратных и фигурных скобок. Так, на десятом уровне вам придётся отслеживать неестественную для глаз мешанину, где даже отступы не помогут. В таких ситуациях намного удобнее иметь дело с закрывающими тэгами XML.
неестественную для глаз мешанину, где дажеНе могу представить. Опять же, JSON проще однозначно отформатировать отступами, чтобы всё было понятно, а в XML атрибуты и дочерние элементы непонятно, как отделять (речь про варианты с множеством атрибутов, которые не влезают в строку).
Как формат для передачи данных, в обоих форматах (XML и JSON) не хватает ссылок (внутренних ссылок между объектами в документе)
Читать JSON действительно легче. А вот писать ИМХО сложно и противно, в основном из-за запятых.
P.S. Использовать JSON в качестве формата для конфигурационных файлов — смертный грех
Ссылки, за столько лет ни разу не было в них нужды, но тоже не проблема, например так:
{
"prop1": {
"prop11": "val1"
},
"prop2": "#ref://prop1/prop11"
}
да после парсинга надо будет пробежаться по объекту и заменить #ref:// на ссылку на объект.
Но лучше чтобы объекты были простые и плоские.
Использовать JSON в качестве формата для конфигурационных файлов — смертный грех
Если XML, уж лучше JSON, но после множества перепробованных форматов, я склоняюсь, что лучший формат конфигурации, это старый добрый ini, простой, лаконичный, читабельный и даже если где то нет для него парсера, можно самому написать в 3 строки, иногда еще короче.
В теории.
На практике, когда они используются, их не обрабатывают нормально, а делают всякие костыльные решения, вроде удаления неймспейсов перед чтением, или читая, игнорируя неймспейсы.
Так же, как никто не обрабатывает нормально XML схему перед чтением.
Суть в том, что XML это сложное решение, которое требует промышленного подхода в работе, и в эпоху скрама и аджайла с ним точно никто не будет работать нормально, к сожалению.
Сделать поддержку какого-нибудь сложного XML-based формата или конфига за пару дней никто ж е даст — это ж чуть ли не Epic Story, за которую нужно делать продуктовые таски.
Сравним два документа
<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 имя типа отображается на имя тэга.
Рассмотрим для примера вот такую страницу: https://portal.eaeunion.org/sites/odata/_layouts/15/Registry/Share/CardView.aspx?Code=P.TS.01&EntityId=646 (это случайная карточка из случайного реестра, не ищите в выборе реестра и карточки скрытых смыслов)
Вы уверены, что запихнув все эти данные в JSON вы упростите передачу информации, а не усложните?
Как показывает практика — XML-базы очень быстро превращаются именно в этот вариант.
К примеру, если вы найдете XML-исходник для документа по ссылке выше — вы не найдете там никаких данных в комментариях или в нарушающем семантику тэге.
А вот если расширение требуется… То тут веселье и начинается.
Добавление новых сущностей начинается с расширения схемы и ее согласования. Что значительно лучше чем JSON, где никому даже в голову не приходит использовать какую-то глупую схему и ее согласовывать, в результате чего о новой схеме все узнают по факту поломки взаимодействия, и хорошо еще если оно не на проде поломалось...
Добавление новых сущностей начинается с расширения схемы и ее согласования.Это идеал, который я очень редко видел применяющимся на практике. Особенно если данные должны «протуннелировать» через несколько слоёв. Потому что в этом случае гораздо проще договорится, скажем, что альтернативные имена познаются, по прежнему, в тег , но отделяются там запятыми или пробелами или ещё как нибудь. Ну вспомните хотя бы про аттрибут «class» в XHTML!
Что значительно лучше чем JSON, где никому даже в голову не приходит использовать какую-то глупую схему и ее согласовывать, в результате чего о новой схеме все узнают по факту поломки взаимодействия, и хорошо еще если оно не на проде поломалось...Опять-таки, из практики: поломка — это гораздо лучше, чем когда у вас всё «как бы работает»… но неправильно. И да, отсутствие схемы сразу автоматически означает, что её не нужно согласовывать, а также, при грамотном использовании, то, что если у
вас несколько потребителей, то про ваши расширения, которые касаются не всех, не нужно будет всем и сообщать.
А вот как раз в таких случаях и нужны пространства имен на которые тут уже жаловались. В общую схему добавляется <xs:any namespace="..." processContents="lax" />
и все. Кому эти данные предназначены, с тем согласовывается дополнительная схема, а остальные эти элементы игнорируют.
Но это же не так. Посмотрите на мои примеры, на пример с которого всё началось. Да, блин, посмотрите на OOXML — это, между прочим, международный стандарт. 6546 страниц документации. А описание принтера, с которым этот документ свёрстан — это, я извиняюсь, CDATA. Почти как тот «строковый элемент с именем xml», с которого всё началось.
Думаете это мелкая деталь реализации, которая мало на что влияет? Ага, я вам щаз губозакатывательную машинку подарю: вся вёрстка в MS Office завязана на характеристики конкретного принтера, для которого документ верстается. Вся. Вплоть до того, что если вы верстаете книжку под какой-нибудь матричник 360dpi, а потом пытаетесь послать её в типографию, чтобы там её распечатали на устройстве с 300dpi или 1200dpi, то зачастую сможете обнаружить что у вас в книжке стало другое количество страниц!
А вы говорите — сограсовывание схем и пространства имён… Ага. Щаз.
Может где-нибудь в NASA ваши идеи и будут работать, но в других местах… 90% разработчиков на поддрежку пространств имён просто забьют. А 90% из оставшихся реализуют поддержку — но сделают это с ошибками. Потому что док они не читают, ничего ни с чем не согласовывают, а код пишут путём дёрганья ответов на случайные вопросы на StackOverflow.
Это не то, что стоит обсуждать и не то, с чем стоит бороться — это просто данность. За написание программ и закрытие «тасков» платят, а за согласование «схемы» — нет. Всё дальнейшее из этого следует.
Вы уверены, что запихнув все эти данные в JSON вы упростите передачу информации, а не усложните?Уверен. Именно потому что данные будут иногда не лезть в оговоренный способ представления — и его придётся менять.
Вместо того, чтобы впихивать круглую палку в квадратное отверстие «очень сильным программистом», которое потом нужно будет расхлёбывать на стороне парсера.
Строковый элемент с именем 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
, я думал что это очевидно.
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'а…
Именно поэтому мне кажется, что реально решаемая этой спекой задача отличается от заявленной.
Если вы предположите, что и схему и документ породили люди, которые имели больше опыта работы с написанием документации, чем с написанием кода и потому понимали нужды 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»…
Представьте себе мир, в котором у HTML-документов и ответов API в точности одинаковая структура. В таком мире JSON, возможно, не стал бы таким популярным, как сегодня.
А ведь JSON-подобный HTML — неплохая идея для современных сайтов, где большие тексты уже не особо распространены.
Имхо, не хватает вспомогательных стандартизованных технологий наподобие XSLT, XQuery, XPath. Но если сравнивать json и yaml, то последний всё-таки предпочтительнее, т.к. комментарии есть и меньше ненужной избыточности
Т.е. берем какие-нибудь простейшие и очевидные решения, придаем им статус прорывных технологий и пишем громкую статью.
{ "title": "Post title", "body": "Post Body" }
Однако в очередной раз не вышло серебряной пули. Уже начали появляться инструменты типа Swagger. Вопрос времени когда введут схемы и нэймспейсы.
Непрерывный рост JSON