Module: Aspera::Yaml
- Defined in:
- lib/aspera/yaml.rb
Class Method Summary collapse
-
.find_duplicate_keys(node, parent_path = nil, duplicate_keys = nil) ⇒ Array<String>
List of duplicate keys with their paths and occurrences.
-
.safe_load(yaml) ⇒ Object
Safely load YAML content, raising an error if duplicate keys are found.
Class Method Details
.find_duplicate_keys(node, parent_path = nil, duplicate_keys = nil) ⇒ Array<String>
Returns List of duplicate keys with their paths and occurrences.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/aspera/yaml.rb', line 11 def find_duplicate_keys(node, parent_path = nil, duplicate_keys = nil) duplicate_keys ||= [] parent_path ||= [] return duplicate_keys unless node.respond_to?(:children) if node.is_a?(Psych::Nodes::Mapping) counts = Hash.new(0) key_nodes = Hash.new{ |h, k| h[k] = []} node.children.each_slice(2) do |key_node, value_node| if key_node&.value counts[key_node.value] += 1 key_nodes[key_node.value] << key_node find_duplicate_keys(value_node, parent_path + [key_node.value], duplicate_keys) end end counts.each do |key_str, count| next if count <= 1 path = (parent_path + [key_str]).join('.') occurrences = key_nodes[key_str].map{ |kn| kn.start_line ? kn.start_line + 1 : 'unknown'}.map(&:to_s).join(', ') duplicate_keys << "#{path}: #{occurrences}" end else node.children.to_a.each{ |child| find_duplicate_keys(child, parent_path, duplicate_keys)} end duplicate_keys end |
.safe_load(yaml) ⇒ Object
Safely load YAML content, raising an error if duplicate keys are found
41 42 43 44 45 |
# File 'lib/aspera/yaml.rb', line 41 def safe_load(yaml) duplicate_keys = find_duplicate_keys(Psych.parse_stream(yaml)) raise "Duplicate keys: #{duplicate_keys.join('; ')}" unless duplicate_keys.empty? YAML.safe_load(yaml) end |