Преобразование вложенных хеш-ключей из CamelCase в snake_case в Ruby

Я пытаюсь создать гем-оболочку API, и у меня возникают проблемы с преобразованием хеш-ключей в более Rubyish формат из JSON, возвращаемого API.

JSON содержит несколько уровней вложения, как хешей, так и массивов. Я хочу рекурсивно преобразовать все ключи в snake_case для упрощения использования.

Вот что у меня есть на данный момент:

def convert_hash_keys(value)
  return value if (not value.is_a?(Array) and not value.is_a?(Hash))
  result = value.inject({}) do |new, (key, value)|
    new[to_snake_case(key.to_s).to_sym] = convert_hash_keys(value)
    new
  end
  result
end

Вышеупомянутый метод вызывает этот метод для преобразования строк в snake_case:

def to_snake_case(string)
  string.gsub(/::/, '/').
  gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
  gsub(/([a-z\d])([A-Z])/,'\1_\2').
  tr("-", "_").
  downcase
end

В идеале результат будет примерно таким:

hash = {:HashKey => {:NestedHashKey => [{:Key => "value"}]}}

convert_hash_keys(hash)
# => {:hash_key => {:nested_hash_key => [{:key => "value"}]}}

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

Попытка решить все это во вспомогательном классе, а не изменять фактические функции Hash и String, если это возможно.

Заранее благодарю.

29
задан Andrew Grimm 3 January 2012 в 02:05
поделиться