澄清YAML语法和Ruby解析

时间:2013-08-22 16:07:52

标签: ruby parsing yaml

我是YAML和Ruby的新手。我使用以下Ruby代码来解析YAML文件:

obj = YAML::load_file('test.yml')

“test.yml”的以下YAML文件内容是否有效?

案例1:

test

在这种情况下,我没有指定test的值(类似test : true)但我的Ruby解析代码不会引发错误。我认为这是一种无效的YAML语法。

案例2:

:test : true

在这种情况下,Ruby代码将test视为符号而不是字符串,当我执行puts obj[:test]时,它将结果返回为“true”。这是Ruby的东西吗?其他语言会将其解释为字符串":test"

案例3:

:test : true
:test : false

在这种情况下,我的Ruby代码不是为重新定义:test而抛出错误,而是采用:test的最新值(false)。为什么是这样? YAML语法是否允许重新定义元素,在这种情况下只获取最新值?

2 个答案:

答案 0 :(得分:4)

案例1: YAML允许unquoted scalars或“裸”字符串未用引号括起来。与引用的字符串相比,它们不太灵活,因为您不能在不创建模糊语法的情况下使用某些字符,但Ruby解析器确实支持它们。

1.9.3-p448 > YAML::parse('test').to_ruby
=> "test"

案例2:正如您所猜测的那样,这是特定于Ruby的,因为YAML没有“符号”的概念。将YAML mapping转换为Ruby哈希时,以冒号开头的标量键被解释为符号而不是字符串。

案例3:根据YAML对mapping的定义,键必须是唯一的,因此在给出您的示例时,严格的解析器应该抛出错误。看起来Ruby解析器更宽松,并允许使用last-value-wins规则多次定义相同的密钥。在本机Ruby哈希中也允许这样做。

1.9.3-p448 > YAML::parse("test: true\ntest: false").to_ruby
=> {"test"=>false}
1.9.3-p448 > { 'test' => true, 'test' => false }
=> {"test"=>false}

答案 1 :(得分:2)

了解YAML解析器如何转换为Ruby结构的好方法是编写输出YAML的Ruby代码,并查看它正在做什么:

这是一个基本哈希:

require 'yaml'
foo = {'test' => true} # => {"test"=>true}
foo.to_yaml # => "---\ntest: true\n"

使用符号作为键的哈希:

foo = {test: true}
foo.to_yaml # => "---\n:test: true\n"

具有冲突键的哈希,导致第一个被最后一个重写:

foo = {test: true, test: false}
foo # => {:test=>false}
foo.to_yaml # => "---\n:test: false\n"

YAML正在创建哈希,但哈希不能有重复的密钥;如果他们这样做,碰撞导致第二次替换第一次。

Yaml Cookbook at the YamlForRuby site”也是一个很好的资源。