我的控制器收到一个JSON字符串在参数中,看起来像这样:
{"serialized"=>"{"key":{"subkey1":"value","subkey2":"value"}"}
在我的控制器中,我尝试如下:
JSON.parse(params[:serialized], symbolize_names: true)
返回:
{:"key"=>{:subkey1=>"value", :subkey2=>"value"}
所有嵌套子键都用符号表示;键被以一种奇怪的方式符号化,所以它不响应哈希[key],而是响应哈希["key"]。
如果我遍历Rails堆栈:
ActiveSupport::JSON.decode(params[:serialized]).symbolize_keys
我得到以下结果:
{:"key"=>{"subkey1"=>"value", "subkey2"=>"value"}
几乎与第一个相同,除了嵌套键;他们没有被象征。
我甚至尝试遍历哈希,试图手动标记键;没有成功:
Hash[params[:serialized]{ |k, v| [k.to_sym, v] }] # returns {:"key"=>{"subkey1"=>"value", "subkey2"=>"value2"}
为什么会发生这种情况?为什么键的符号是:"key"而不是:key?
乌利希期刊指南删除了最后一行(我怎么可能解决这个问题,因为我需要我的哈希来回答哈希[key]而不是哈希["key"].),所以这个问题看起来不那么实用,更理论化。
try on rails console.
require 'json'
string = {"serialized"=>"{"key":{"subkey1":"value","subkey2":"value"}"}
hash = JSON.parse string
我同意@boulder上面所说的。但是因为Hash[params[:serialized].symbolized_keys.map{ |k, v| [k.to_sym, v.symbolize_keys] }]
是用来表示到一级的。我真的不会这么做的,永远不会。
这可能与你所要求的不同,但在Rails中访问哈希的键/值通常适合于hash.key
而不是hash[:key]
或hash['key']
。
这是主要约定,也是访问@user.name
等字段的原因。
Rails通过OpenStruct
实现了这一点。要使用它,您可以这样做:
@foo = ActiveSupport::JSON.decode(params[:serialized]).symbolize_keys
obj = OpenStruct.new(@foo)
obj.key #=> {"subkey1"=>"value", "subkey2"=>"value"}
但是,再次,OpenStruct创建对象直到使用.key
而不是':key'访问的一个级别。为了帮助实现这一点,我们有了Recursive OpenStruct,它完美地完成了这项工作。
我个人认为,在这种情况下,你应该在Rails中工作。
首先,:key和:"key"是表达完全相同事物的两种方式。事实上,如果你这样做:
> :key == :"key"
=> true
所以给定一个散列,比如
h = {:"key" => "value"}
h[:key]
=> "value"
其次,如果您有嵌套的散列,您不仅希望手动标记键,还希望在值
中标记键。Hash[params[:serialized].symbolized_keys.map{ |k, v| [k.to_sym, v.symbolize_keys] }]
当然,如果你有多个级别的"鸟巢",你需要更详细的东西
旧主题,但对于那些可能落在它上面的,Rails提供了方法deep_symbolize_keys
,似乎正是op解析json后需要的:
hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
hash.deep_symbolize_keys
# => {:person=>{:name=>"Rob", :age=>"28"}}
来源:https://apidock.com/rails/Hash/deep_symbolize_keys