В YAML должен ли цитируемый скаляр интерпретироваться парсером как строка?
Я видел в интернете совет, что если вы хотите, чтобы скалярное значение YAML обрабатывалось как строка, вы должны заключить его в кавычки:
foo : "2018-04-17"
В приведенном выше примере этот совет предназначен для того, чтобы сказать мне, что значение 2018-04-17
будет обработан любым данным синтаксическим анализатором YAML как строковый тип его родного языка. Например, SnakeYAML, если бы этот совет был верным, интерпретировал бы это как java.lang.String
а не как java.util.Date
, (Как это бывает, SnakeYAML интерпретирует это как java.util.Date
, цитаты или нет, поэтому я задаю этот вопрос.)
Но хотя этот совет может работать с любым конкретным парсером, я не вижу, где в YAML 1.2. Спецификация этот совет может прийти. Самое близкое, что я могу найти, это следующее предложение:
YAML позволяет представлять скаляры в нескольких форматах. Например, целое число "
11
"Также может быть написано как"0xB
". Теги должны указывать механизм для преобразования форматированного содержимого в каноническую форму для использования в тестировании на равенство. Как и стиль узла, формат представляет собой детали представления и не отражается в дереве сериализации и графе представления.
И этот:
Скалярный стиль является деталью представления и не должен использоваться для передачи информации о содержимом, за исключением того, что простые скаляры различаются с целью разрешения тегов.
И этот:
Обратите внимание, что разрешение не должно учитывать детали представления, такие как комментарии, отступы и стиль узла.
Тем не менее, я вижу много документов YAML, которые основаны на рекомендациях двойных кавычек "значение означает, что это будет проанализировано как строка", что заставляет меня думать, что я что-то неправильно понял. Есть ли споры по этому вопросу?
1 ответ
Соответствующий раздел из спецификации YAML 1.1 (обратите внимание, что SnakeYaml - это YAML 1.1, и поэтому спецификация 1.2 не обязательно применяется):
Не требуется, чтобы все теги полного представления были явно указаны в символьном потоке. Во время синтаксического анализа узлам, которые пропускают тег, присваивается неспецифический тег: "?" Для простых скаляров и "!" Для всех остальных узлов. [...]
Рекомендуется разрешить узлы, имеющие неспецифический тег "!", Как "tag:yaml.org,2002:seq", "tag:yaml.org,2002:map" или "tag:yaml.org,2002:str”в зависимости от вида узла. Это соглашение позволяет автору потока символов YAML осуществлять некоторую степень контроля над процессом разрешения тегов. Путем явного указания простого скаляра с неспецифическим тегом "!" Узел разрешается в виде строки, как если бы он был заключен в кавычки или записан в стиле блока. Обратите внимание, однако, что каждое приложение может переопределить это поведение. Например, приложение может автоматически определять тип языка программирования, используемый в исходном коде, представленном как непрозрачный скаляр, и разрешать его соответствующим образом.
Таким образом, чтобы подвести итог, процессор YAML не обязан анализировать скаляры в кавычках как строки, и YAML также не определяет, какой тип tag:yaml.org,2002:str
отображается на. И на самом деле, большинство реализаций YAML следуют только частям этого совета. Например, если вы десериализуете YAML в POJO/JavaBean с помощью SnakeYaml, вы обычно не используете какие-либо явные теги в своем YAML, но ваши сопоставления разрешаются в соответствующие классы Java в структуре корневого класса, а не в общий Map
это то, что предлагает этот совет (так как все отображения без явных тегов получают !
неспецифический тег).
Обратите внимание, что это было изменено в YAML 1.2:
Во время синтаксического анализа узлам, не имеющим явного тега, присваивается неспецифический тег: "!" Для непростых скаляров и "?" Для всех остальных узлов.
Это ближе к большинству реализаций, но, например, если вы десериализуете в класс class Foo { String bar; }
, это все равно будет загружать хотя bar
это не строка, а имя поля:
"bar": some value
Таким образом, совет для использования YAML заключается в том, чтобы указать желаемую структуру на стороне приложения - в SnakeYaml вы бы задали тип корневого класса, и тогда каждое значение будет отображаться на требуемый тип в его точке иерархии, если оно может отображать там, независимо от того, цитируется он или нет. В целом, для приложения имеет больше смысла указывать, какой тип значения он ожидает по всей иерархии, а не автор YAML, чтобы сделать это через кавычки. Это также соответствует спецификации YAML, которая говорит
Разрешение тега узла должно зависеть только от следующих трех параметров: (1) неспецифический тег узла, (2) путь, ведущий от корня к узлу, и (3) содержимое (и, следовательно, вид) узла.
Разрешение тега - это термин YAML для определения типа цели. И разрешено определять целевой тип на основе его положения в иерархии: корневой тип определяется тем фактом, что элемент является корнем документа YAML, а в случае SnakeYaml может подаваться через API. Все остальные типы определяются тем, что они являются потомками корневого типа.
Последнее замечание: если вы действительно хотите, чтобы что-то было строкой, !!str 2018-04-17
будет делать, так как он устанавливает определенный тег для узла.