在Ruby中,如何在加载YAML文档时警告哈希中的重复键?

时间:2011-02-06 02:22:11

标签: ruby yaml

在下面的Ruby示例中,是否有一种模式让YAML NOT 以静默方式忽略重复键'one'?

irb(main):001:0> require 'yaml'
=> true
irb(main):002:0> str = '{ one: 1, one: 2 }'
=> "{ one: 1, one: 2 }"
irb(main):003:0> YAML.load(str)
=> {"one"=>2}

谢谢!

4 个答案:

答案 0 :(得分:2)

我帮助维护我使用的YAML文件的一件事是编写代码,以便从Ruby中的已知结构开始生成它。这让我开始了。

然后,我会写一个小片段来加载它并输出它使用PrettyPrintAwesome Print解析的内容,以便我可以将其与文件进行比较。

我还根据需要对字段进行排序,以便于查找重复项。

答案 1 :(得分:1)

有一个涉及短绒的解决方案,但我不确定它是否与之相关 你,因为它不是100%的Ruby解决方案。因为我不知道,所以我会发布它 任何在Ruby中这样做的方法:

您可以使用yamllint命令行工具:

sudo pip install yamllint

具体来说,它有一个规则key-duplicates来检测重复的密钥:

$ cat test.yml
{ one: 1, one: 2 }

$ yamllint test.yml
test.yml
  1:11      error    duplication of key "one" in mapping  (key-duplicates)

答案 2 :(得分:0)

没有。您必须决定如何重命名密钥,因为散列键必须是唯一的 - 我会采取一些解决方法,例如手动查找相同的密钥并在执行YAML::load之前重命名它们。

答案 3 :(得分:0)

使用Psych,您可以遍历AST树以查找重复的键。我在测试套件中使用以下帮助程序方法来验证我的i18n翻译中没有重复的键:

def duplicate_keys(file_or_content)
  yaml = file_or_content.is_a?(File) ? file_or_content.read : file_or_content
  duplicate_keys = []

  validator = ->(node) do
    if node.is_a?(Psych::Nodes::Mapping)
      duplicates = node.children.select.with_index { |_, i| i.even? }.group_by{ |child| child.value }.select { |value, nodes| nodes.size > 1 }
      duplicates.each do |key, nodes|
        duplicate_key = {
          file: (file_or_content.path if file_or_content.is_a?(File)),
          key: key,
          occurrences: nodes.map { |occurrence| "line: #{occurrence.start_line + 1}" }
        }.compact

        duplicate_keys << duplicate_key
      end
    end

    node.children.to_a.each { |child| validator.call(child) }
  end

  ast = Psych.parse_stream(yaml)
  validator.call(ast)

  duplicate_keys
end