如何在Ruby on Rails中将company.address.city转换为对象

4

我有几个参数,想要从中构建一个深层嵌套的JSON对象,如下所示:company.address.city company.address.state

这是我的参数:

{"business_type"=>"company", "company.address.city"=>"Gold Coast", "company.address.line1"=>"123 fake street", "company.address.state"=>"QLD", "company.name"=>"test"}

我期望的是:

business_type: "company",
company{
  address{
     city: "Gold Coast",
     line1: "123 fake street",
     state: "QLD",
  },
name: "test"
}
3个回答

3

如果需要,可以采用方法形式

h = {"business_type"=>"company", "company.address.city"=>"Gold Coast", "company.address.line1"=>"123 fake street", "company.address.state"=>"QLD", "company.name"=>"test"}

def flatten_keys(hash)
  hash.each_with_object({}) do |(key,value), all|
    parts = key.split('.').map!(&:to_sym)
    new = parts[0...-1].inject(all) { |h, k| h[k] ||= {} }
    new[parts.last] = value
  end
end

flatten_keys(h)

这将被打印出来

=> {:business_type=>"company", :company=>{:address=>{:city=>"Gold Coast", :line1=>"123 fake street", :state=>"QLD"}, :name=>"test"}}

希望这可以帮到您。

1
这不是最优雅的代码,但它能够工作:
input = {"business_type"=>"company", "company.address.city"=>"Gold Coast", "company.address.line1"=>"123 fake street", "company.address.state"=>"QLD", "company.name"=>"test"}

res = input.reduce({}) do |memo, (keys_str, val)|
  keys = keys_str.split(".")
  last_key = keys[-1]
  hsh = memo
  keys[0...-1].each do |key|
    hsh[key] ||= {}
    hsh = hsh[key]
  end
  hsh[last_key] = val
  memo
end

puts res

输出结果为:

{"business_type"=>"company", "company"=>{"address"=>{"city"=>"Gold Coast", "line1"=>"123 fake street", "state"=>"QLD"}, "name"=>"test"}}


做得好,完美地运行了- 不过kkp的回答也同样完美,我选择那个回答作为最佳答案,纯粹是因为我理解它。但对于其他需要答案的人来说,这个也很好用。 - CodeCabin

1

纯 Ruby:您可以定义一个自定义方法来进行深度赋值,例如像这样,受到https://dev59.com/L1sW5IYBdhLWcg3wwZcP#54122742的启发:

def nested_set(h, keys, value)
  # keys = keys.map(&:to_sym)
  last_key = keys.pop
  position = h
  keys.each do |key|
    position[key] = {} unless position[key].is_a? Hash
    position = position[key]
  end
  position[last_key] = value
end

然后,只要将数据输入作为参数,就可以很容易地在需要时调用它:
parameters.each.with_object({}) { |(k, v), res| nested_set(res, k.split('.'), v) }

#=> {"business_type"=>"company", "company"=>{"address"=>{"city"=>"Gold Coast", "line1"=>"123 fake street", "state"=>"QLD"}, "name"=>"test"}}

或者定义一个更方便的方法。
def do_that_on parameters
  parameters.each.with_object({}) { |(k, v), res| nested_set(res, k.split('.'), v) }
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接