Я пытаюсь создать гем-оболочку 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, если это возможно.
Заранее благодарю.