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

Tom*_*Jam 6 ruby yaml

在下面的例子红宝石,是有一个模式有YAML 默默地忽略重复键"一"?

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}
Run Code Online (Sandbox Code Playgroud)

谢谢!

小智 5

使用 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, parent_path) do
    if node.is_a?(Psych::Nodes::Mapping)
      children = node.children.each_slice(2) # In a Mapping, every other child is the key node, the other is the value node.
      duplicates = children.map { |key_node, _value_node| key_node }.group_by(&: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: parent_path + [key],
          occurrences: nodes.map { |occurrence| "line: #{occurrence.start_line + 1}" },
        }.compact

        duplicate_keys << duplicate_key
      end

      children.each { |key_node, value_node| validator.call(value_node, parent_path + [key_node.try(:value)].compact) }
    else
      node.children.to_a.each { |child| validator.call(child, parent_path) }
    end
  end

  ast = Psych.parse_stream(yaml)
  validator.call(ast, [])

  duplicate_keys
end
Run Code Online (Sandbox Code Playgroud)


Jak*_*mpl 0

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