Формат данных YAML чрезвычайно усложнён. Он задумывался как удобный для человека, но в стремлении к этой цели сложность настолько увеличилась, что, по моему мнению, его разработчики достигли противоположного результата. В YAML есть куча возможностей выстрелить себе в ногу, а его дружелюбие обманчиво. В этом посте я хочу продемонстрировать это на примере.
Данный пост является нытьём и он более субъективен, чем мои обычные статьи.
YAML очень, очень сложен
JSON прост. Вся спецификация JSON состоит из шести синтаксических диаграмм. Это простой формат данных с простым синтаксисом, и больше в нём нет ничего. В отличие от него, YAML сложен. Настолько сложен, что его спецификация состоит из десяти глав с разделами, пронумерованными на четыре уровня в глубину, и отдельным списком ошибок.
Спецификация JSON не разделена на версии. В 2005 году в неё внесены два изменения (удаление комментариев и добавление научной записи для чисел), но с тех пор она заморожена (уже почти два десятка лет). Спецификация YAML имеет версии. Последняя версия довольно свежая, 1.2.2 от октября 2021 года. YAML 1.2 существенно отличается от 1.1: один и тот же документ в разных версиях YAML может парситься по-разному. Ниже мы увидим много примеров этого.
JSON настолько очевиден, что Дуглас Крокфорд заявляет, что он был открыт, как явление, а не придуман. Я не нашёл никакой информации о том, сколько времени ему понадобилось на создание спецификации, но это были скорее часы, чем недели. Переход YAML с версии 1.2.1 на 1.2.2 потребовал многолетних усилий команды специалистов:
Эта ревизия стала результатом нескольких лет работы новой команды разработки языка YAML. Каждый человек в этой команде обладает глубокими знаниями языка, написал и поддерживает важные опенсорсные фреймворки и инструменты YAML.
Более того, эта команда планирует активно развивать YAML, а не замораживать его.
При работе со столь сложным форматом, как YAML, сложно понимать все фичи и особенности его поведения. Существует целый веб-сайт, посвящённый выбору одного из 63 синтаксисов многострочных строк. Это значит, что человеку очень сложно предсказать, как спарсится конкретный документ. Чтобы подчеркнуть это, давайте рассмотрим пример.
YAML-документ из Ада
Рассмотрим следующий документ.
server_config:
port_mapping:
# Expose only ssh and http to the public internet.
- 22:22
- 80:80
- 443:443
serve:
- /robots.txt
- /favicon.ico
- *.html
- *.png
- !.git # Do not expose our Git repository to the entire world.
geoblock_regions:
# The legal team has not approved distribution in the Nordics yet.
- dk
- fi
- is
- no
- se
flush_cache:
on: [push, memory_pressure]
priority: background
allow_postgres_versions:
- 9.5.25
- 9.6.24
- 10.23
- 12.13
Проанализируем его по частям и посмотрим, как эти данные преобразуются в JSON.
Шестидесятеричные числа
Давайте начнём с того, что можно найти в конфигурации среды исполнения контейнера:
port_mapping:
- 22:22
- 80:80
- 443:443
{"port_mapping": [1342, "80:80", "443:443"]}
Ой, а что здесь произошло? Оказывается, числа от 0 до 59, разделённые двоеточиями — это шестидесятеричные (по основанию 60) числовые литералы. Эта загадочная фича присутствовала в YAML 1.1, но была незаметно удалена из YAML 1.2, поэтому в зависимости от версии, которую использует парсер, элемент списка спарсится как
1342
или как "22:22"
. Формату YAML 1.2 уже больше десяти лет, но если вы предположите, что он широко поддерживается, то ошибётесь: последняя версия libyaml на момент написания (которая, среди прочего, используется и в PyYAML) реализует YAML 1.1 и парсит 22:22
как 1342
.Якоря, псевдонимы и тэги
Следующий фрагмент на самом деле невалиден:
serve:
- /robots.txt
- /favicon.ico
- *.html
- *.png
- !.git
YAML позволяет создать якорь добавив
&
и имя перед значением, а позже вы сможете ссылаться на это значение при помощи псевдонима: *
, за которым следует имя. В этом случае якоря не заданы, поэтому псевдонимы недействительны. Давайте пока избавимся от них и посмотрим, что произойдёт.serve:
- /robots.txt
- /favicon.ico
- !.git
{"serve": ["/robots.txt", "/favicon.ico", ""]}
Теперь интерпретация зависит от используемого парсера. Элемент, начинающийся с
!
— это тэг. Эта фича предназначена для того, чтобы позволить парсеру преобразовывать довольно ограниченные типы данных YAML в расширенные типы, которые могут существовать на языке реализации. Тэг, начинающийся с !
, интерпретируется парсером по своему усмотрению, часто вызовом конструктора с соответствующим именем и передачей ему значения, следующего за тэгом. Это значит, что загрузка непроверенного YAML-документа в общем случае небезопасна, потому что может привести к исполнению произвольного кода. (В Python можно избежать этой проблемы, используя yaml.safe_load
вместо yaml.load
.) В приведённом выше случае PyYAML не удаётся загрузить документ, потому что она не знает тэг .git
. YAML-пакет языка Go менее строг, он возвращает пустую строку.Проблема Норвегии
Эта проблема настолько широко известна, что её назвали проблемой Норвегии:
geoblock_regions:
- dk
- fi
- is
- no
- se
{"geoblock_regions": ["dk", "fi", "is", false, "se"]}
Что здесь делает
false
? Литералы off
, no
и n
и их различные вариации с заглавным регистром (но не все!) в YAML 1.1 считаются false
, а on
, yes
и y
считаются true. В YAML 1.2 эти альтернативные написания булевых литералов больше не допускаются, но в реальном мире они встречаются столь часто, что соответствующий стандарту парсер будет испытывать трудности с чтением многих документов. Поэтому разработчики YAML-библиотеки языка Go приняли решение реализовать собственный вариант, находящийся примерно посередине между YAML 1.1 и 1.2; в зависимости от контекста парсер ведёт себя по-разному:YAML-пакет поддерживает бОльшую часть YAML 1.2, однако сохраняет часть поведения 1.1 для обратной совместимости. Булевы литералы YAML 1.1 (yes/no, on/off) поддерживаются, если они декодируются в типизированное значение bool. В противном случае они ведут себя как строка.
Стоит заметить, что библиотека ведёт себя так только с версии 3.0.0, выпущенной в мае 2022 года. Более ранние версии ведут себя иначе.
Ключи, не являющиеся строками
В JSON ключи всегда являются строками, однако в YAML они могут любыми значениями, в том числе и булевыми.
flush_cache:
on: [push, memory_pressure]
priority: background
{
"flush_cache": {
"True": ["push", "memory_pressure"],
"priority": "background"
}
}
В сочетании с ранее описанной особенностью интерпретации
on
как булева значения это приводит к тому, что одним из ключей словаря становится true
. Если это происходит, то результат зависит от языка, выполняющего преобразование в JSON. В Python это превращается в строку "True"
. В реальном мире ключ on
встречается часто, потому что используется в GitHub Actions. Мне было очень любопытно узнать, что ищет парсер GitHub Actions внутри, "on"
или true
.Случайные числа
Если оставлять строки без кавычек, они запросто могут превращаться в числа.
allow_postgres_versions:
- 9.5.25
- 9.6.24
- 10.23
- 12.13
{"allow_postgres_versions": ["9.5.25", "9.6.24", 10.23, 12.13]}
Возможно, список — это натянутый пример, но представьте, что нужно обновить файл конфигурации, в котором указано единственное значение 9.6.24, и нужно заменить его на 10.23. Вспомните ли вы, что нужно добавить кавычки? Проблема становится ещё более коварной из-за того, что многие приложения с динамической типизацией при необходимости преобразуют неявным образом число в строку, поэтому бОльшую часть времени документ будет работать нормально, однако в некоторых контекстах может ломаться. Например, следующий шаблон Jinja принимает и
version: "0.0"
, и version: 0.0
, но для первого варианта идёт только по ветви true.{% if version %}
Latest version: {{ version }}
{% else %}
Version not specified
{% endif %}
Другие примеры
Это всё, что я смог уместить в один вымышленный пример. Есть и другие загадочные поведения YAML, не вошедшие в него: директивы, целочисленные значения, начинающиеся с
0
и являющиеся восьмеричными литералами (но только в YAML 1.1), ~
как альтернативное написание null
и ?
, добавляющий сложный ключ преобразования.Подсветка синтаксиса вас не спасёт
Вероятно, вы заметили, что ни в одном из моих примеров не включена подсветка синтаксиса. Возможно, я несправедлив к YAML, потому что подсветка синтаксиса выделяет специальные конструкции, поэтому мы, по крайней мере, сможем видеть значения, а не обычные строки. Однако из-за множества используемых версий YAML и разных уровней изощрённости функций подсветки на это полагаться нельзя. И в данном случае я не пытаюсь придираться: Vim, генератор моего блога, GitHub и Codeberg на самом деле подсвечивали пример документа из поста каждый по-своему. Ни один из них не выделил одно и то же подмножество значений как строки!
Шаблонизация YAML — поистине ужасная идея
Надеюсь, теперь понятно, что работа с YAML, по меньшей мере, имеет свои тонкости. Ещё более тонкая тема — конкатенация и изолирование произвольных текстовых фрагментов таким образом, что результат становится валидным YAML-документом, но не тем, который вы ожидаете. Сюда же стоит добавить значимость для YAML пробелов (whitespace). В результате мы получаем формат, о сложностях шаблонизации которого создают мемы. Я искренне не понимаю, почему инструменты, основанные на такой подверженной ошибкам практике, получили столь большое внимание, несмотря на то, что существует более безопасная, простая и мощная альтернатива: генерация JSON.
Альтернативные форматы конфигураций
Я думаю, основная причина доминирования YAML, несмотря на его проблемы, заключается в том, что долгое время он был единственным жизнеспособным форматом конфигураций. Часто нам требуются списки и вложенные данные, поэтому «плоские» форматы наподобие ini исключаются. XML шумный и вручную его писать неудобно. Но самое важное, что нам нужны комментарии, а это исключает применение JSON. (Как мы говорили ранее, изначально в JSON существовали комментарии, но их удалили, потому что люди начали помещать в них директивы парсинга. Думаю, это подходящий выбор для формата сериализации, однако из-за этого JSON не подходит как язык конфигураций.) Итак, если на самом деле нам нужна модель данных JSON, только с синтаксисом, допускающим комментарии, то какие у нас есть варианты?
- TOML — TOML во многом похож на YAML: по большей мере в нём используются те же типы данных; синтаксис не такой многословный, как в JSON; также он позволяет использовать комментарии. В отличие от YAML, в нём не так много возможностей выстрелить в ногу, потому что строки всегда заключаются в кавычки, а значит, вы не получите значения, которые выглядят как строки, но ими не являются. TOML обладает широкой поддержкой, поэтому есть вероятность, что вы сможете найти парсер TOML для своего языка программирования. Он даже есть в стандартной библиотеке Python (в отличие от YAML!). Слабое место TOML заключается в глубоко вложенных данных.
- JSON с комментариями, JSON с запятыми и комментариями — существуют различные расширения JSON, расширяющие его как раз настолько, чтобы он стал удобным форматом конфигураций без добавления особой сложности. Наверно, самым распространённым является JSON с комментариями (JSON with comments), поскольку он используется как формат конфигураций в Visual Studio Code. Основной недостаток этих форматов в том, что они ещё не набрали популярность (пока!), потому что не так широко поддерживаются, как JSON и YAML.
-
Простое подмножество YAML — многие из проблем YAML вызваны элементами без кавычек, которые походят на строки, но ведут себя иначе. Этого легко избежать: всегда заключайте в кавычки все строки. (Опытного YAML-разработчика можно узнать по тому, что он на всякий случай закавычивает все строки.) Мы можем принять решение всегда использовать
true
иfalse
вместоyes
иno
, держась подальше от неявных особенностей. Сложность здесь в том, что любая конструкция, не запрещённая явным образом, рано или поздно всё равно попадёт в кодовую базу, а я не знаю ни одного хорошего инструмента, способного принудительно обеспечивать применение безопасного подмножества YAML.
Генерация JSON как более совершенного YAML
Часто выбор формата зависит не от нас и приложение может принимать только YAML. Однако не всё потеряно, ведь YAML — это надмножество JSON, поэтому любой инструмент, способный создавать JSON, можно использовать для генерации YAML-документа.
Иногда изначально приложению требуется только один формат конфигурации, однако со временем может появиться много схожих строк файлов конфигурации и вам захочется передавать между ними части, а также абстрагировать повторения. Такое случается, например, с Kubernetes и GitHub Actions. Когда язык конфигураций не поддерживает абстракций, люди обычно обращаются к шаблонизации, а это плохая идея по описанным выше причинам. Лучше подойдут настоящие языки программирования, возможно, предназначенные для конкретной области. Мои любимые — это Nix и Python:
- Nix — это язык, используемый менеджером пакетов Nix. Он был создан для написания определений пакетов, однако достаточно хорошо работает в качестве формата конфигураций (и на самом деле используется для конфигурирования NixOS). Благодаря функциям, привязкам let и интерполяции строк он является мощным инструментом для абстрагирования повторяющейся конфигурации. Его синтаксис столь же легковесен, как и у TOML, и он может выполнять экспорт в JSON или XML. Например, он хорошо подходит для упрощения повторений в workflow-файле GitHub Actions.
-
Python — документы JSON можно с минимальной адаптацией использовать как валидные литералы Python, к тому же Python поддерживает замыкающие запятые и комментарии. Он имеет переменные и функции, мощную интерполяцию строк и встроенный
json.dump
. Автономный файл Python, выводящий JSON на stdout, послужит вам добрую службу!
Наконец, в этой категории есть инструменты, которые я недостаточно много использовал, чтобы рекомендовать с уверенностью, но заслуживающие упоминания:
- Dhall — Dhall похож на Nix, но с типами. Он менее распространён, и лично мне имена его встроенных функций кажутся громоздкими.
- Cue — как и Dhall, Cue интегрирует информацию о типах/схемах в формат конфигурации. Cue — надмножество JSON, но несмотря на это, файлы, в которых используются функции Cue, кажутся мне незнакомыми. Я оставлю Cue для изучения в будущем, однако пока не встречал задач, в которых Cue мог бы быть самым подходящим решением.
- Hashicorp Configuration Language — я недостаточно долго пользовался HCL, чтобы сформировать о нём определённое мнение, но там, где я работал с ним, его потенциал абстрагирования казался более ограниченным, чем, например, у Nix.
Заключение
YAML задумывался как более дружественная для человека альтернатива JSON, но из-за всех своих особенностей он стал таким сложным форматом с таким множеством странных и неожиданных поведений, что людям сложно предсказать, как будет парситься конкретный YAML-документ. Если вам нужен формат конфигураций, то TOML — это дружественный формат без выстрелов в ногу, присущих YAML. В случаях, когда вы вынуждены пользоваться YAML, жизнеспособным решением будет генерация JSON из более подходящего языка. Генерация JSON также открывает возможности для абстрагирования и многократного использования в той степени, которую сложно безопасно достичь шаблонизацией YAML.
Комментарии (133)
identw
14.01.2023 10:15+15Вы перечислили DHall, cue, HCL. Но пропустили достаточно популярный jsonnet. Который точно также работает со структурами данных, вместо того чтобы шаблонизиоровать текст, и на мой взгляд мощнее перечисленных.
А вот шаблонить ямл как текст, как делает helm это конечно дичь. Я тоже в шоке что это обрело такую популярность.
А по поводу самого yaml. Да есть странности. Но я вот за всю практику (8 лет примерно) никогда не попадал на описанные проблемы. Всегда если сомневался просто использовал кавычки. Мне его читать удобнее, поэтому конфигам на ямле я рад. А вот указанные toml и xml мне читать гораздо сложнее, томл со средней и большой вложенностью совсем не в читаемую кашу превращается. Конечно наверное с большой вложенностью все форматы не читаемы для человека. А вот при умеренной вложенности, на мой взгляд yaml удобнее всего читать. IMHO
Возможно дело ещё в том, что я кроме случаев использования helm не шаблоню ямл, а в большинстве случаев генерирую его программно. А если пишу или правлю руками, то использую кавычки почти всегда когда точно не уверен. Простые правила, но видимо благодаря ним я до сих пор не испытываю ненависти к ямлу, хотя от коллег часто слышу.
Aquahawk
14.01.2023 10:16+94Наконец кто-то это сказал вслух. Yaml это исчадие ада, не читаемое, не удобное, но обросшее мифами, что оно якобы читаемое и удобное. Я не знаю насколько у людей должна отсутствовать собственная точка зрения, когда им показывают откровенно плохую вещь и говорят что она хорошая, потому, что её автор написал, что она хорошая и кто-то на конференции тоже сказал, что это хорошо. Нет это плохо. Это было очевидно для меня с момента его появления, я избегаю его везде, но объяснять людям верующим в прекрасные технологии, что эти технологии дерьмо нет накакого желания, вера аргументами не бьётся. И чем больше я вижу как со временем мои предположения оказываются верными, тем больше я доверяю себе, а не докладчику со смузи на очередной модной конференции, у которого из аргументов только awsome, flexible, designed for humans
Revertis
14.01.2023 13:55+7Я не знаю насколько у людей должна отсутствовать собственная точка зрения, когда им показывают откровенно плохую вещь и говорят что она хорошая, потому, что её автор написал, что она хорошая и кто-то на конференции тоже сказал, что это хорошо.
Сразу священными писаниями запахло :))
Aquahawk
14.01.2023 14:14+8Я уже давно смотрю на технологии с точки зрения веры и религии. И у молодых программистов это сейчас кажется развито больше чем раньше, просто нужно это учитывать, сложность технологий растёт, необходимость делать выбор в ограниченные сроки без полного понимания остаётся, да еще и в пиар некоторые техи умеют лучше чем другие. Но вообще, как только ты предагаешь опцию про которую никто никогда не говорил на конференциях и не писал статей, сразу вопрос, а почему бы не поступить как вот там дядя говорил?
Revertis
14.01.2023 15:14Да, всё так, это апелляция к авторитету.
Aquahawk
14.01.2023 15:27+3С одной стороны да, а с другой меня всегда можно обвинить в https://ru.m.wikipedia.org/wiki/Склонность_к_подтверждению_своей_точки_зрения И простого решения кто прав неи. Все эти термины всегда обоюдоостры и играясь с ними можно вывернуть всё как угодно, всегда нужно видеть людей, их задачи и мысли, а не паттерны поведения.
Хотя я нашёл хак, как побеждать в апелляции к авторитету, например выступить на конференции и в споре ссылаться на свой доклад, тогда некоторых отпускает и они начинают разумно общаться не боясь что они сейчас, о боже, сделают что-то, что авторитетом не одобрено.
ReadOnlySadUser
14.01.2023 20:38+1Меня лично отпустило, полосе того, как я пару раз особо не думая, вернувшись с конференции попытался на чистой инициативе затащить кое какие плюшки в проект)
В общем, оба раза закончилось это дело полным крахом, так что теперь я 7 раз думаю, а потом делаю. Но как мне кажется, это обычный нормальный здоровый путь из джуна в сеньоры, а потом и на пенсию)
Aquahawk
14.01.2023 20:44+2Ну вот про пенсию тоже верно подмечено, и хочется не быть старпёром, а иногда такую ересь предлагают, что хоть вешайся. Но новые крутые штуки безусловно есть, особенно отметил бы прогресс в языках, typescript и rust показали как можно хорошо подумать, и сделать крутую вещь. А то, что coffeescript и ruby умерли, хотя хайпа в своё время подняли море, говорит о том что нужно подождать буквально лет 5 и ересь проветрится.
ReadOnlySadUser
14.01.2023 20:50+3Я согласен с тем, что в Rust есть крутые идеи и процессе изучения у меня было ощущение, что наконец-то придумали "С++ здорового человека". И всё же попытки написать на нем что-то более или менее серьезное привели меня к мысли, что как-то не очень дружественен язык. В общем, удовольствия не получил, вернулся в свой С++ мирок и черпаю из Rust иногда вдохновение)
А вот про typescript согласен. При условии опыта работы с типизированными языками, typescript после JavaScript как глоток свежей воды в жаркий день)
Aquahawk
14.01.2023 20:52+6Rust - концепт который показал, что так можно было. Я уверен что будущее системного программирования либо за тотальной переработкой раста или за его идеологическим наследником.
ReadOnlySadUser
14.01.2023 20:57+1Мелькал Carbon не так давно на какой-то конфе) Чисто концептуально он мне понравился больше Rust, я бы поставил на него)
AnthonyMikh
15.01.2023 18:54+5В FAQ Carbon прямым текстом написано If you can use Rust, ignore Carbon
ReadOnlySadUser
16.01.2023 09:35Вопрос не в том, что там написано, а что в итоге взлетит в массах.
И пока что Carbon выглядит как Kotlin для С++. И мне это нравится. А как выглядит Rust - не уверен. Концептуально Rust классный, я даже когда-то тут сам топил за него а каждом комментарии, но последнее время сомнения меня терзают.
rmrfchik
16.01.2023 14:31Я вижу у раста несколько категории вещей, которые сделаны круто.
Управление памятью. Они первые, кто сделал то, что сделал и понять, насколько это круто-правильно и как можно было бы сделать по другому пока сложно. Нужны исследования и новые языки с другими попытками сделать так же, но по другому.
Система типов. Божечки, наконец-то не стали копировать ООП, дак-тайпинг или, прости лямбда, прототипинг. Сели, подумали и взяли хорошее из истории. Где-то получилось не очень, но в целом достойно твёрдой пятёрки и даже с плюсом.
Тулинг. Прям молодцы, что тулинг это для них одна из первоочередных задач.
Вот для понимания управления памятью нужно менять мозг, а за всё остальное рукоплещу.
Wesha
17.01.2023 07:47Управление памятью. Они первые, кто сделал то, что сделал и понять, насколько это круто-правильно и как можно было бы сделать по другому пока сложно.
А вот с этого момента поподробнее можно? Интересно же.
наконец-то не стали копировать ООП, дак-тайпинг или, прости лямбда, прототипинг. Сели, подумали и взяли хорошее из истории.
И с этого тоже.
blind_oracle
14.01.2023 20:18+16Если из YAML выкинуть всё это говно непонятное и вызывающее UB - он лучше и читаемее JSON. Я использую их для конфигов своих сервисов, проблем не испытаываю, но при этом игнориую все эти доп. фичи. Выстрелить в ногу, конечно, возможности остаются, но сильно ограничены.
olku
14.01.2023 10:31+7Yaml не хватило схемы вместо версии парсера, как у JSON. Большая часть проблем с валидацией бы отпала.
acc0unt
14.01.2023 11:05+25YAML мог бы стать тем самым остро нужным "стандартом JSON с комментариями". Вместо этого он стал вот этой вот огромной химерой, которая ухитряется быть менее читаемой и интуитивной чем сам JSON, который он в теории должен был улучшить. Отвратительно.
Вот упомянутый выше JSON5 выглядит жизнеспособным.
gudvinr
15.01.2023 21:01+1YAML был разработан параллельно с JSON, а не как замена ему и появился примерно в то же время.
Поэтому было бы странно, если бы он стал "стандартом JSON", не являясь основанным на JSON.
То, что JSON документ является валидным YAML документом, было формализовано позднее, и в общем-то это заслуга простоты JSON, а не из-за того что YAML специально был придуман с оглядкой на это.
bozman
14.01.2023 12:54+14Причем истоки этого кошмара — в противоречивом ТЗ. Типа, сейчас мы сделаем формат, который будет одновременно человекочитаемым, иметь произвольную древовидную структуру, типизацию на все случаи жизни... а еще модное на момент создания форматирование отступами. И многострочные строки, куда без них. На выходе естественно ужастик со слоганом "они думали, что страшнее XML ничего нет... " :)
nin-jin
14.01.2023 13:51Не вижу противоречий в этом ТЗ. Просто авторы ямла не справились с ним. Бывает.
Aquahawk
14.01.2023 14:15+5В поисках волшебника найдёшь сказочника. Хорошее ТЗ это не перечисление всего хорошего что сделать надо и всего плохого, что не надо.
bozman
14.01.2023 17:29+7Вот, например, это загадочное кастование 1:30 в 90 как раз от слишком буквально понятого человекочитания. Это ж типа чтобы человек написал полторы минуты "по человечески", а парсер считал 90 секунд по компьютерному. Вместо того чтобы либо молча интерпретировать как строку, либо упасть с ошибкой. Но это же так фу-фу, недружественно.
aamonster
15.01.2023 00:41При наличии типизации, кажется, было бы вполне дружественно. Но, конечно, это сделало бы синтаксис контекстно-зависимым, что тоже больно.
mayorovp
15.01.2023 09:53+1При наличии типизации лучше бы позволить преобразованию происходить по правилам типизации, а не по правилам YAML.
Вот в том же .NET промежуток времени хранится в TimeSpan. Какой смысл в преобразовании строки в число перед преобразованием в TimeSpan?
miga
14.01.2023 13:02+6томл вместо ямла - это такое лекарство, которое хуже болезни, как виндовые ини-файл, только более прОклято.
rule of thumb для ямла очень прост - не злоупотребляйте опциональностью кавычек для строк и используйте { } если не уверены в синтаксисе мап/списков.
dpytaylo
14.01.2023 13:16+8Я использовал TOML в конфигах раста, и никаких проблем с его прочтением/написанием не было. Главное же, не использовать его там, где будет большая вложенность.
blind_oracle
14.01.2023 20:20+2Даже 2-3 уровня вложенности в TOML уже вызывают боль. Поэтому уехал на YAML без всего этого ужаса из статьи.
DirectoriX
14.01.2023 14:01+6Для меня радость от чтения/написания YAML закончилась в тот момент, когда оказалось что массивы в нём странненькие.
Непустой массив: после названия ставим двоеточие, а затем на каждой строке увеличиваем отступ и перед значением ставим маркер-
:
Пустой массив: после названия ставим двоеточие иnonempty_arr: - val1 - val2
[]
, иначе утиностипизирует в null:empty_arr: []
Да, я понимаю, что массивы можно писать и в одну строку, тогда как раз и будут нужны эти квадратные скобки:nonempty_arr2: [val1, val2]
Но почему-то именно непустое объявление пустого массива меня сломало. С тех пор если я выбираю формат конфигов — то только pretty-printed JSON.Mingun
14.01.2023 14:09+2И как там, в pretty-printed JSON, непустое объявление пустого массива (а также объекта и строки) вас не смущает? Странно, что именно это вас «сломало».
NekoiNemo
14.01.2023 14:39+1А можно с примером что именно должно в нем смущать?
Mingun
14.01.2023 15:13Пример смотрите в комментарии выше (на который я отвечал).
NekoiNemo
14.01.2023 15:26В комментарии DirectoriX не было примера такого массив в pretty-printed JSON. И, если я правильно понял что "непустое объявление пустого массива" означает необходимость писать "[]"... То что именно должно в этом смущать?
В JSON как и во всех нормальных форматах, есть синтаксис, которому нужно следовать независимо от того пустой массив или нет.
В YAML же, синтаксиса для массивов 2 (как минимум). при этом один синтаксис используется для массивов простых объектов И позволяет объявлять пустой массив, а второй синтаксис позволяет делать массивы сложных обхектов, НО не позволяет объявлять пустой массив. Что приводит к интересным моментам как, например, невозможность просто удалить строку с последним элементом массива (т.к. это сделает этот ключ равным null, ан е пустому массиву) и вместо этого необходимость переписать этот массив на однострочный синтаксис. А когда потом потребуется снова добавить значение - переписать обратно.
Такая несогласованность не может не "ломать" разработчика привыкшего к "форматам трезвого человека". А вот в JSON я что-то подобных проблем не припомню, отсюда и просьба привести пример.
Mingun
14.01.2023 15:34+1И, если я правильно понял что "непустое объявление пустого массива" означает необходимость писать "[]"...
О том и речь. Но комментатора выше это смутило настолько, что он решил отказаться от yaml в пользу pretty-printed JSON, при том, что он от такого перехода вообще ничего не выиграл, ведь ровно то, что его «смутило» в yaml, присутствует и в pretty-printed JSON, только yaml, в отличие от этого, предлагает более удобный синтаксис в определённых ситуациях, а pretty-printed JSON — нет.
dopusteam
14.01.2023 15:40+4Есши перечитаете, то поймете, что комментатора выше смутило не просто [] для пустого массива, а слишком сильная разница в описании пустого массива и не пустого массива
Mingun
14.01.2023 16:00+2Разницы никакой. Массив можно описывать либо «со скобками», либо «с отступами». Не нравится второй вариант — всегда используйте первый, в чём проблема? Да, второй вариант не покрывает всех возможных вариантов задания массивов, но такова плата за удобство. Кроме того, пустые массивы в реальной жизни встречаются кратно реже заполненных, так что и определяющим фактором в отказе от yaml этот факт тоже выглядит крайне странно.
nin-jin
14.01.2023 15:45-2В JSON недопустима висячая пунктуация, так что добавление/удаление последнего элемента списка при многострочном форматировании приводит к необходимости менять предыдущий элемент.
NekoiNemo
14.01.2023 15:59+7Под "последним" я подразумевал "последний оставшийся. Т.е.
"array": [ {"foo": 1} ]
"array": [ ]
А вот в YAML удалив последний элемент из
array: -foo: 1
мы получим
array:
что есть null а не пустой массив. И вместо этого нужно переключится на другой синтаксис массива
array: []
И когда после этого требуется добавить значение обратно - в JSON все так же логично и consistent, в вот в YAML мы не можем в этот пустой массив добавить новый `foo: 2` - для этого нужно переключаться обратно на многострочный синтаксис массива.
Так понятнее?
PrinceKorwin
14.01.2023 17:01-2Это не очень большая проблема. Элементы массива можно описывать так:
"arr": [
1
, 2
, 3
]
Тогда при удалении последнего элемента массива не нужно трогать предыдущую строку.
nronnie
15.01.2023 20:21+1Тут, понимаете, скорее всего недоработка самого приложения. Если оно читает конфиг, который пишут руками (а YAML практически только для этого и используется), то оно должно в той или иной степени нормально обрабатывать различные "вольности" в этом конфиге, как, например, использовать разумное значение по умолчанию вместо пропущеного. В данном случае, лично я, даже не задумывась, в самом приложении просто сразу заменял бы
null
на пустой массив.
staticmain
14.01.2023 14:21+5Если нам в JSON нужны комментарии, то мы используем в ванильном JSON следующие конструкции:
Либо
{ "#01" : "Перечисляет возможные фичи, доступные для этого узла", "#02" : "Выключенное значение можно обозначить как false,", "#03" : "или не указывать его вовсе", "features" : { "#01" : "Включена ли TMS", "tms" : true, "#11" : "Использует ли узел функциональность корзины", "#12" : "Её можно безопасно отключить, если не хватает места", "recycle_bin" : false } }
либо
{ "_comment_01" : "Перечисляет возможные фичи, доступные для этого узла", "_comment_02" : "Выключенное значение можно обозначить как false,", "_comment_03" : "или не указывать его вовсе", "features" : { "_comment_01" : "Включена ли TMS", "tms" : true, "_comment_10" : "Использует ли узел функциональность корзины", "_comment_11" : "Её можно безопасно отключить, если не хватает места", "recycle_bin" : false } }
Кроме того, мы используем реализацию парсера, который допускает дубликаты ключей, поэтому в лично нашем проекте мы можем даже делать вот так:
{ "" : "Перечисляет возможные фичи, доступные для этого узла", "" : "Выключенное значение можно обозначить как false,", "" : "или не указывать его вовсе", "features" : { "" : "Включена ли TMS", "tms" : true, "" : "Использует ли узел функциональность корзины", "" : "Её можно безопасно отключить, если не хватает места", "recycle_bin" : false } }
Aquahawk
14.01.2023 15:30+3любой парсер обязан допускать дубликаты ключей, поведение при этом не определено. А вообще я так тожеькомменты пишу иногда, но это не сработает если коммент нужно проставить в массиве.
ermouth
14.01.2023 17:05+4Формально да, не определено, и это проблема, которая привела, например, к cve 2017-12635. Там за счёт того, что парсер на Эрланге брал первое вхождение, а js – последнее, можно было самого себя админом сделать в один post.
aborouhin
14.01.2023 16:51+1Мне кажется, такого рода комментариям (поясняющим значения настроек) самое место в description в JSON схеме. По крайней мере, если не предполагается, что JSON-файлы будут редактировать в обычных текстовых редакторах, не умеющих эти пояснения из схемы подтягивать и отображать как подсказки.
А вот комментарии по поводу конкретных значений настройки ("тут мы поставили 3, потому что с 2 тормозит, а с 4 вылетает") да, только как-то так и писать. Но надо думать, как возможность их наличия в схему зашить...
KivApple
16.01.2023 01:21+1Ещё комментарии бывают полезны для временного отключения/замены куска конфига. Например, чтобы быстро менять опции при отладке.
dmi3mart
14.01.2023 18:55+4Наверное, немаловажный нюанс - это область применения. JSON хорош там, где нужен стандартизированный и надёжный формат данных, т.е. почти везде. Тем не менее, в статье упоминается, что YAML задумывался как человекопонятный формат, который удобно писать руками, и есть масса рутинных ситуаций, где большинство описанных ТСом проблем никогда и не встретятся, а скорость и удобство ручной работы при этом в разы возрастёт.
Например, я работаю с October CMS, где CRUD'ы конфигурируются как раз простыми YAML-файлами. Изо дня в день приходится писать что-то вроде:
fields: is_active: label: 'foo.catalog::lang.products.fields.is_active.label' type: switch span: full default: true comment: 'foo.catalog::lang.products.fields.is_active.comment' vendor_code: label: 'foo.catalog::lang.products.fields.vendor_code.label' type: text span: auto category: label: 'foo.catalog::lang.products.fields.category.label' type: relation nameFrom: title span: auto emptyOption: 'foo.catalog::lang.products.fields.category.empty_option' title: label: 'foo.catalog::lang.products.fields.title.label' type: text span: auto
Аналогичный конфиг набивать руками в виде JSON или нативного массива в PHP гораздо сложнее и неудобнее. При этом за годы работы и тонны написанных конфигов я ни разу не встретился с каким-либо неочевидным поведением парсера YAML.
Мой вывод: каждый инструмент хорош на своем месте, если ты знаешь его особенности и можешь использовать его максимально эффективно.
Aquahawk
14.01.2023 19:01+4Однака yaml часто пытаются запихать туда куда он не лезет. И вообще общий вывод опыта программирования за уже почти 20 лет, ечли это сделано чтобы было удобно писать а не читать, получается плохо. Потому что мы чаще читаем чем пишем.
nronnie
15.01.2023 20:30+2Однака yaml часто пытаются запихать туда куда он не лезет.
Ну это же не вина YAML. Если кто-то забивает молотком саморезы, а они потом вываливаются, то это ведь не значит, что при забивании гвоздей надо выкинуть молоток и начать забивать их шуруповертом.
semmaxim
14.01.2023 20:29+7Я правильно понимаю, что все перечисленные проблемы - всего лишь следствие того, что строки не обязательно заключать в кавычки?
Aquahawk
14.01.2023 20:40+14Да, но авторам было лень заключать строки в кавычки потому что именно это напрягало их в json. И они объявили войну кавычкам, изобрели это и проиграли.
ReadOnlySadUser
14.01.2023 20:55+2Лень нажать одну кнопку? Воистину человеческая лень не имеет границ)
Aquahawk
14.01.2023 21:00+7Я с вами полностью согласен. Но к сожалению некоторые программисты поражены такой вредной мыслью как: "если это одинаковое действие нужно повторять, то от него нужно избавиться" Там подключается миллион мифов что повторение действий это неэффективно, что это место для ошибки и нужно сделать так чтобы никакого повторящегося действия не было. Я встречал это когда при парсинге надо проверять аргументы или еще когда нибудь когда есть похожие куски кода которые хорошо бы оставить как естьа не пытаться обобщить, не все обобщения полезны. Толи это из Совершенного кода, толи из Рефакторинга вылезло, толи ещё откуда, но такое поверие весьма распостранено, хотя по моему мнению гораздо более вредно чем полезно.
i360u
15.01.2023 02:31Я удивительную вещь сейчас скажу, но объектную нотацию JavaScript можно писать прямо... на языке JavaScript. Таким образом, вы получаете и комментарии, и типизацию, и валидацию и все остальное, что потом элементарно можно преобразовать в обычный JSON. А еще, это все можно подключать в виде модуля, подсвечивать, тайпчекать и линтить в IDE, использовать асинхронные API прямо внутри... И лишних кавычек в ключах нет. Тут, конечно, встанет вопрос использования JS-рантайма, если вы, к примеру, пишете на питоне, но можно воспринимать этот рантайм как своего рода парсер...
Aquahawk
15.01.2023 07:13+1я так и перешёл на то, что все конфиги у меня .js а не .json Отлично работает.
i360u
15.01.2023 15:32-2Ага, еще и изоморфные конфиги отлично пишутся. И если использовать свежие https-импорты (на ноде), то стадию преобразования в JSON вообще можно опустить. Ну, кроме случаев, когда данные нужно парсить очень быстро, JSON.parse работает быстрее чем парсинг деклараций в js (если кто не знал).
Andrey_Solomatin
16.01.2023 03:31Не только JavaScript, но и в Python.
Хотя в Python чаще немного другой подход к таким конфигам. Там просто пишется файл который присваивает нужные переменные, константами или кодом.
Например:
- https://docs.djangoproject.com/en/4.1/topics/settings/
- https://www.sphinx-doc.org/en/master/usage/configuration.html
DmitryKoterov
15.01.2023 04:27+6Имхо json5 (или jsonc, не знаю точно, в чем отличие) покрывает практически все необходимости. И главное, это ведь просто литерал, который валиден в JS. Т.е. если взять какой-нибудь Prettier, отформатировать им литерал из js-файла и положить в json5-файл, то вот это он и будет один в один.
По сравнению с json, json5 опциональны кавычки для ключей словаря, есть комментарии, и завершающие запятые игнорируются. Парсится он так же быстро, как парсится json (если сравнивать библиотеки на C). Непонятно, почему бы в какой-то момент просто не взять и не сделать в json-парсерах дефолтную поддержку json5, это ведь ничего не сломает.
SerafimArts
15.01.2023 09:37+2В json5 спеке есть всякие NaN, +Inf, -Inf, которых может не быть в некоторых языках. Поэтому просто так везде добавить поддержку не получится.
mayorovp
15.01.2023 10:07Если сериализацию-десериализацию производить не просто так, а с учётом схемы — проблемой это не станет.
KivApple
16.01.2023 01:25+4В каких языках нет IEEE754 и насколько они актуальны в 2023 году?
SerafimArts
16.01.2023 19:10Хм… Сходу могу назвать SQL, где NaN/INF хоть и могут быть, но не являются флоатами/даблами в большинстве реализаций (Ну например MySQL… Ну или PostgreSQL, где это numeric).
Ещё ANSI C (Насколько я нагуглил). Но возможно ошибаюсь, нашёл только для C++.
P.S. Ну я то не спорю, но мне казалось всегда, что это довольно специфичные типы, которые хоть и являются частью системы типов (потомком флоата) большинства языков, но не могут быть представлены однозначной последовательностью битов в двоичном представлении. Ну, типа, как выглядит, например,
-INF
в LE, чтобы его можно было записать в двоичном виде и потом прочитать на любом языке, получив тот же-INF
в качестве значения флоата?Cerberuser
17.01.2023 08:25+2Ну, типа, как выглядит, например,
-INF
в LE, чтобы его можно было записать в двоичном виде и потом прочитать на любом языке, получив тот же-INF
в качестве значения флоата?А это разве не часть стандарта? Сам его текст найти в свободном доступе не удалось, но беглый гуглёж предложил вот такое описание:
For single-precision values:
Positive infinity is represented by the bit pattern 7F800000
Negative infinity is represented by the bit pattern FF800000
For double-precision values:
Positive infinity is represented by the bit pattern 7FF0000000000000
Negative infinity is represented by the bit pattern FFF0000000000000
То есть, как раз вполне конкретное битовое представление.
mapcuk
16.01.2023 10:34Действительно, а зачем специальные форматы если можно взять какой lua или python, но чтоб все переменные были неизменяемые.
belozer0
16.01.2023 22:16+2Данный пост является нытьём и он более субъективен, чем мои обычные статьи.
Батенька, вы не умеете ныть про ямль, давайте научу.
Лет восемь-десять назад мне посчастливилось участвовать в локализации игры по популярному сериалу по не менее популярным книжкам.
Моей задачей было вынуть текст на перевод и потом переведённое засунуть назад.
То, что эти деятели писали игру на рельсах, оставим на их совести. В конце концов там есть до фига бэкэндов локализации, включая божественный геттекст. Но эти рыцари решили использовать симпл, то есть тупо ямльки. Их было в проекте что-то около 2054 штук. Валидатором (самым добрым из) признаны были валидными 2 (прописью: два блин!) из 2054. Остальными ни одного. И я руками писал парсер невалидного ямль и рассоватор обратно переведёнышей.
Ямль идиотский формат, но люди тупее и злее.
capuccio
16.01.2023 22:16Был (да и есть) такой простой и хороший формат: cfg. Поддерживается стандартной библиотекой libconfig. Незаслуженно забыт и здесь никем не упомянут.
nronnie
Ну, с двоеточием, по-моему, все знают. И, к тому же, насколько я знаю,
- 22:22
в любом случае не спарсится как"22:22"
, а даст{ "22": "22" }
.Вот про "Норвегию" не знал, поэтому автора плюсую. :)
longclaps
Кратчайший ликбез по сабжу, "Learn X in Y minutes, where X=yaml" - это yaml-документ в 200 строк.
Про "yes/no is boolean" там есть.
Почитайте, может еще что новое для себя узнаете )
Aquahawk
Зачем изучать сложное, если есть простое?
nin-jin
Например, формат Tree, который проще и нагляднее всех названных в статье. Изучается за пару минут. Парсер пишется за час.
tempick
Я знал, что увижу этот комментарий как только прочитал заголовок статьи
ReadOnlySadUser
Я смотрю на YAML и мне больно.
Я смотрю на Tree и думаю, что YAML был не так уж и плох.
P.S.
Почему по ссылке утверждается что JSON нельзя парсить поточно? Я не знаю есть ли такие парсеры или нет, но чисто концептуально я не вижу проблем написать такой. В чем конкретно там проблема-то?
Cerberuser
Как я понял - в том, что файл в любой момент может закончиться с незакрытым объектом, и тогда весь результат разбора летит в мусор.
ReadOnlySadUser
С тем же успехом можно говорить, что в YAML встретится невалидный синтаксис и результат разбора пойдёт в мусор.
nin-jin
yaml может содержать множество документов. Полностью полученные документы можно спокойно обрабатывать, даже если какой-то из последующих обрывается на середине.
omgiafs
И тут мне вспомнилось, как в не самой незаметной и мелкой игре Insurgency: Sandstorm не менее полугода жил баг: настройки разгрузки постоянно слетали в дефолтные, т е. настроишь для инсурга-снайпера штук 5 профилей, и для остальных ролей не меньше, а при следующей загрузке игры там пустота. Полгода так было, не меньше. Все плакали. Игра на движке UE4, файлы конфигураций в JSON. Лично я сначала написал батник, который тупо копировал JSON с сохранёнными профилями на место файла профилей перед запуском игры. Но это достало в конец, и я начал исследование проблемы: вносишь правки в профиль, закрываешь игру, копируешь файл профилей в сторону, запускаешь игру - профили слетели. Штош, и новый файл профилей в сторону. Потом просто парсишь профили - вуаля, новый профиль - просто дефолтный валидный JSON, а в твоём файле профилей оказывается незакрытой одна скобка. Ставишь скобку в нужном месте, файл скармливаешь игре - хоба, игре этот файл нравится, профили не слетают. Просто движок парсил невалидный JSON, и, напоровшись на ошибку, заменял его дефолтным валидным файлом. Написал багрепорт, через неделю поправили. При том, что я не программист и вообще в IT так и не влился.
Полгода был в проде этот баг, Карл. О нём писали всё, включая разрабов, которые в чейнджлогах новых патчей писали, что да, мол, есть такая проблема, до сих пор не вылечили.
После этого случая стал подозревать, что в игростудиях процент нерукожопов такой же, как везде - не более 10-15 :)
mayorovp
На самом деле как только дело доходит до чего-то вспомогательного, вроде сохранения и загрузки JSON, процент "нерукожопов" там оказывается даже меньше среднего по индустрии.
DarthVictor
С тем же успехом незакрытый тег может быть в XML, но поточные SAX парсеры были чуть ли не с момента создания стандарта.
Aquahawk
всё прекрасно json парсится поточно
nin-jin
Что конкретно там написано каждый может почитать сам: https://github.com/nin-jin/slides/tree/master/tree#поточная-обработка
А Робинович вам и не такое напоёт.
shai_hulud
Там голословное уважением и ничего для подтверждения. Поточный xml используется в jabber, ничего не мешает поточно читать JSON.
В том же JSON.NET есть JsonReader который позволяет читать по одному токену, и если надо целиком объекты, можно прочитать файл любого размера условным кодом:
Andrey_Solomatin
Если на главном уровне это список объектов, то парсер который выдаёт по объекту за раз волне реален и удобен. Если у вас мапа и в одном из полей огромный список, то апи не будет простым. А если у все весь файл это одна строка, то парсер подавится, хотя это уж слишком крайний случай.
Кейс со списком на мой взгляд это самый распространённый для огромного джейсона. Хотя это случай можно заменять на формат https://jsonlines.org/ . Парсер легко делается на базе обычного парсера и читалки строк вашего языка програмирования.
bromzh
...если ты его автор.
Мне он напоминает помесь питона и перла, причём самых плохих их сторон: вложенность через отступы (когда при копи-пасте можно потерять пробелы/табы и потом не понимать, где же уехал отступ) и обилие небуквенных символов (типа $,/,@,\) для обозначения разных структур. И в лучших традициях перловских однострочников, всё это write-only вещь.
Andrey_Solomatin
Зависит от инстирументов.
У меня IDE вечно деформирует yaml при вставке в yaml файл.
А вот с Питоном всё норм.
nin-jin
Не выдумывайте, при копипасте отступы никуда сами не уезжают. Пунктуация есть в любом языке. Формат tree имеет лишь один спецсимвол -
\
. Язык json.tree добавляет ещё 3:/
для списков,*
для словарей и-
для комментариев. Всё.Kuch
Вот каждый каждый каждый раз при копировании больших кусков у меня первая строка остаётся с правильным отступом, а все остальные на -1 отступ. Vs code
Я уже просто привык и даже не замечаю, как постоянно правлю это. Но сколько раз я попадал на невалидный yaml из-за этого
nin-jin
Это потому что вы вставляете в конец строки, а не в начало. Надо ставить каретку в начало, вставлять код и табом регулировать его общий уровень отступов.
Cerberuser
То есть, если не регулировать - отступы всё-таки именно что "сами уезжают"?
Kuch
Блин, ну это жесть какая-то. Каждый раз на это тратить время. Мне проще выделить все последующие строки и нажать таб. Но в любом случае, без дополнительных действий просто так не вставляется
nin-jin
Вам в любом случае надо тратить время на адаптацию вставленного кода. Благо массовая регулировка отступов делается за секунду. А если вы намекаете на автоформатирование, то при разбалансировке скобочек, оно такого накреативит, что порой потом пол часа приходится исправлять.
Aldrog
Три действия: отменить переформатирование, добавить пропущенную скобку, применить форматирование. И это только в тех случаях, когда ошибка уже была совершена при копировании.
nin-jin
Отменить форматирование со всеми правками, сделанными пока не заметил косяк.
Долго искать место, где и какой не хватает скобки, долбясь глазами в кривое форматирование.
bromzh
Делать правки с пропущенной скобкой? В файле куча ошибок будет, какие правки?
Но вообще разговор был про блоки отступами. Не скопировал скобку - вылезет ошибка, ты быстро поправишь. Но если блоки только отступами, то никто не подсветит тебе корявый отступ. А некоторые ИДЕ ещё и форматируют при вставке, что только усугубит ситуацию.
nin-jin
От скопипащенного кода почти всегда куча ошибок, пока вы не адаптируете код к контексту.
Если блоки отступами, то корявость ты видишь сам, даже без подсветки.
Aldrog
Но автоформатирование и подсветка синтаксиса решают описанные вами проблемы скобок. Не очень понимаю, зачем вы с этим спорите.
bromzh
Я чаще копирую код из этого-же файла, где контекст уже есть. Фигня в том, что блоки отступами порождают совершенно новый класс проблем.
Такая же проблема может быть и в условном питоне, где ты вставляешь какой-нибудь блок, и код валидный, но делает не то что надо.
Полагаться на слабую плоть, которая может устать и не заметить косяк, когда рядом есть чудо-машина? Ну уж нет. Я что, зря деньги платил?
khajiit
Вы предполагаете, что после вставки и до того момента, как выяснится, что закралась ошибка — с файлом вообще ничего никогда не происходит?
Очень наивно.
Перейдите уже с notepad.exe хотя бы на sublime…
bromzh
По совету проверенных камрадов перешёл на
сублаймvscode. Попробовал язык с отступами и вставку там. Хочу сделать копию child внутри ещё одного child. Но что-то никак не выходит это сделать простым копипастом. Проблема в том, что любой из вариантов после копипаста валидный, но не правильный для меня.Попробовал поганый язык со скобками, там если что-то скопировать лишнее, почему-то сразу видно ошибку.
А если попробовать воссоздать проблему, аналогичную ямловской, то она почему-то не воссаздаётся. Там таких проблем нет как класс.
nin-jin
https://habr.com/ru/post/710414/comments/#comment_25113900
khajiit
Обстоятельный подход, респект.
В саблайме новые строки маркируются слева, рядом с номером, полоской, поэтому зрительно потерять свежую вставку довольно сложно. Есть (был для 3 точно) и плагин для маркировки несохраненных строк.
На первой картинке вы забываете оттабить скопированный текст, хотя на второй поставить запятую — не забываете.
То есть, в одном случае вы пренебрегаете форматом, в другом нет — и это вопрос лишь практики и упрямства, а не недостатка формата.
На второй же ошибку видно только если у вас и начало и конец в пределах даже не поля зрения, а непосредственно области вставки: даже в пределах одного экрана но парой десятков строк ближе к центру блока вы бы ее наверняка пропустили.
Ну и третья картинка явно иллюстрирует разное и неочевидное поведение редактора касательно отступов — тут, скорее, в багтрекер писать надо.
Shannon
По ссылке написано, что минификация или однострочная форма не предусмотрена и не нужна, и то, что с таким форматом другие форматы не нужны.
Как подразумевается работа, например, с curl?
curl -X POST https://site -d {"login":"login","password":"pwd"}' -H 'Content-Type: application/json'
nin-jin
https://stackoverflow.com/questions/34847981/curl-with-multiline-of-json
dolfinus
Нет, для того, чтобы 22 считался ключом, после двоеточия должен быть пробел
pfffffffffffff
А его заметно блин в редакторе???????
Revertis
Если не заметно, то надо менять либо редактор, либо мозг.
pfffffffffffff
Либо формат на не yaml умник
nronnie
Буду знать, но я просто всегда если в "строке" есть двоеточие, то беру её в кавычки давно уже на автомате.
До сих пор никаких фатальных проблем с YAML лично не встречал, хотя регулярно с ним работаю. Формат, понятно, весьма расплывчатый, но говорить, что это прямо "ад" это слишком сильно. Расплывчатость формата можно считать данью некоторому удобству. Никто ведь не говорит, что JavaScript это ад только из-за того что там
;
опциональна. Или что PowerShell это ад, потому что в одних случаях можно просто перенести строку, а в других случаях нужен обратный апостроф, в одних случаях можно задать массив просто как1, 2, 3
, а в других нужен полный синтаксис@(1, 2, 3)
(и кавычки, к слову, там тоже "опционально опциональны" :). В большинстве случаев везде работает простое правило "сомневаешься - не сокращай". Поставь просто лишние кавычки, скобки, точку с запятой и т.п.mayorovp
Тоже неинтуитивное поведение, кстати. В большинстве языков пробел возле спецсимвола считается незначимым.
Siddthartha
первый раз слышу, хотя годами работаю с docker-compose.yml
nronnie
В
docker-compоse
как раз даже в документации есть, чтоports:
надо все в кавычки брать и сказано почему.Wesha
Всю жизнь говорил: умолчания — зло. Хочешь строковое значение — не выйоживайся и не экономь два байта, обрами кавычками.