我不理解什么是YAML标签。

79

我在某种程度上理解,但是我还没有看到一个例子,它所带来的问题比解答更多。

http://rhnh.net/2011/01/31/yaml-tutorial

# Set.new([1,2]).to_yaml
--- !ruby/object:Set 
hash: 
  1: true
  2: true

我理解我们正在声明一个Set标签,但是我不知道后续的哈希映射和它有什么关系。我们是否在声明模式?可以有人展示一下多个标签声明的例子吗?
我已阅读规范:http://yaml.org/spec/1.2/spec.html#id2761292
%TAG ! tag:clarkevans.com,2002:

这是在声明一个模式吗?解析器还需要做些什么才能成功解析文件?需要一种模式文件吗?

http://www.yaml.org/refcard.html

Tag property: # Usually unspecified.
    none    : Unspecified tag (automatically resolved by application).
    '!'     : Non-specific tag (by default, "!!map"/"!!seq"/"!!str").
    '!foo'  : Primary (by convention, means a local "!foo" tag).
    '!!foo' : Secondary (by convention, means "tag:yaml.org,2002:foo").
    '!h!foo': Requires "%TAG !h! <prefix>" (and then means "<prefix>foo").
    '!<foo>': Verbatim tag (always means "foo").

为什么需要主标签和次标签?为什么次标签要引用URI?这样做解决了什么问题?
看到很多“它们是什么”的描述,却没有说明“它们为什么存在”或“它们用于什么”。

2
在你的第一个例子中,#Set.new([1,2]).to_yaml实际上是一条注释-它是一个Ruby语句,将输出其下方的YAML。 - Alex
1个回答

46

我对YAML不是很了解,但我会尝试解释一下:

标签用于表示类型。如您从“refcard”中看到的那样,使用!声明标记。而 %TAG 指令类似于声明标记的快捷方式。

我将以PyYaml作为例子进行演示。 PyYaml可以将!!python/object:的次级标记解析为实际的python对象。双感叹号本身是一种替换,代表!tag:yaml.org,2002:,然后将整个表达式转换为!tag:yaml.org,2002:python/object:。每次创建对象时输入这个表达式有些繁琐,因此我们使用%TAG指令给它取了一个别名:

%TAG !py! tag:yaml.org,2002:python/object:            # declares the tag alias
---
- !py!__main__.MyClass                                # creates an instance of MyClass

- !!python/object:__main__.MyClass                    # equivalent with no alias

- !<tag:yaml.org,2002:python/object:__main__.MyClass> # equivalent using primary tag

如果没有标签注释,节点将根据其默认类型进行解析。以下两种方式是等效的:

- 1: Alex
- !!int "1": !!str "Alex"

这里是一个使用PyYaml展示标签用法的完整Python程序:
import yaml

class Entity:
    def __init__(self, idNum, components):
        self.id = idNum
        self.components = components
    def __repr__(self):
         return "%s(id=%r, components=%r)" % (
             self.__class__.__name__, self.id, self.components)

class Component:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return "%s(name=%r)" % (
            self.__class__.__name__, self.name)

text = """
%TAG !py! tag:yaml.org,2002:python/object:__main__.
---
- !py!Component &transform
  name: Transform
  
- !!python/object:__main__.Component &render
  name: Render

- !<tag:yaml.org,2002:python/object:__main__.Entity>
  id: 123
  components: [*transform, *render]

- !<tag:yaml.org,2002:int> "3"
"""

result = yaml.load(text)

更多信息可在规范中获取。


3
根据YAML 1.2规范,我相信在你的例子中,!!将被扩展为!<tag:yaml.org,2002:> ,它本质上是tag:yaml.org,2002:,而不是!tag:yaml.org,2002:。同样适用于!!python/object,它将被扩展为tag:yaml.org,2002:python/object: - Dreamer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接