В Ruby как предупредить дубликаты ключей в хешах при загрузке документа YAML? - PullRequest
6 голосов
/ 06 февраля 2011

В следующем примере 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 ]

2 голосов
/ 16 апреля 2019

Используя 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
2 голосов
/ 06 февраля 2011

Одна из вещей, которые я делаю, чтобы помочь поддерживать файлы YAML, которые я использую, - это написание кода для первоначального создания его из известной структуры в Ruby.Это заставляет меня начать.

Затем я напишу небольшой фрагмент, который загружает его и выводит то, что он анализировал, используя PrettyPrint или Awesome Print , чтобы я мог сравнитьчто в файл.

Я также сортирую поля по мере необходимости, чтобы облегчить поиск дубликатов.

1 голос
/ 02 февраля 2016

Существует решение, включающее линтер, но я не уверен, что оно будет актуально для вас, поскольку это не решение на 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)
0 голосов
/ 06 февраля 2011

Нет. Вам нужно будет решить, как переименовать ключи, поскольку хеш-ключи должны быть уникальными - я бы выбрал обходной путь, например, вручную отыскивал одинаковые ключи и переименовал их, прежде чем выполнить YAML::load.

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...