[英]Ruby/Rails - issues with JSON.parse/JSON.decode
My controller receives a JSON string inside params which looks like following: 我的控制器在params中接收一个JSON字符串,如下所示:
{"serialized"=>"{\\"key\\":{\\"subkey1\\":"value",\\"subkey2\\":"value"}"}
In my controller I try the following: 在我的控制器中,我尝试以下方法:
JSON.parse(params[:serialized], symbolize_names: true)
Which returns: 哪个回报:
{:"key"=>{:subkey1=>"value", :subkey2=>"value"}
All the nested subkeys were symbolized; 所有嵌套的子键都是符号化的; the key was symbolized in a weird way so it is not responding to hash[key] , but does to hash["key"] .
密钥以一种奇怪的方式进行符号化,因此它不响应hash [key] ,而是哈希[“key”] 。
If I go through the Rails stack: 如果我浏览Rails堆栈:
ActiveSupport::JSON.decode(params[:serialized]).symbolize_keys
I get back the following: 我回过头来看:
{:"key"=>{"subkey1"=>"value", "subkey2"=>"value"}
Almost same as the first one except for nested keys; 除了嵌套键之外,几乎与第一个相同; they are not being symbolized.
他们没有被象征。
I've even tried looping through hash trying to symbolize the keys manually; 我甚至试图通过哈希循环尝试手动符号化键; with no success though:
虽然没有成功:
Hash[params[:serialized]{ |k, v| [k.to_sym, v] }] # returns {:"key"=>{"subkey1"=>"value", "subkey2"=>"value2"}
Why is this happening? 为什么会这样? Why is the key symbolized as :"key" instead of :key ?
为什么键符号为:“key”而不是:key ?
UPD Removed last line (How could I possibly fix that since I need my hash to answer to hash[key] and not hash["key"] .) so the question looks less pragmatic and more theoretic. UPD删除了最后一行(我怎么可能修复它,因为我需要我的哈希来回答hash [key]而不是hash [“key”] 。)所以问题看起来不那么务实,而且更具理论性。
try on rails console. 试试rails console。
require 'json'
string = {"serialized"=>"{\"key\":{\"subkey1\":"value",\"subkey2\":"value"}"}
hash = JSON.parse string
I agree with what @boulder said above. 我同意@boulder在上面所说的话。 But since,
Hash[params[:serialized].symbolized_keys.map{ |k, v| [k.to_sym, v.symbolize_keys] }]
但是从那以后,
Hash[params[:serialized].symbolized_keys.map{ |k, v| [k.to_sym, v.symbolize_keys] }]
Hash[params[:serialized].symbolized_keys.map{ |k, v| [k.to_sym, v.symbolize_keys] }]
is for symbolizing till 1 level. Hash[params[:serialized].symbolized_keys.map{ |k, v| [k.to_sym, v.symbolize_keys] }]
用于符号化直到1级。 I won't really go for this, ever. 我永远不会真的去做这件事。
This is probably different from what you are asking for, but accessing hash's key/values in Rails, is usually suited like hash.key
instead of hash[:key]
or hash['key']
. 这可能与您要求的不同,但在Rails中访问哈希的键/值通常适合像
hash.key
而不是hash[:key]
或hash['key']
。
This is the primary convention, and is the reason, how one can access fields like @user.name
etc. 这是主要的约定,也是人们如何访问
@user.name
等字段的原因。
Rails implements this by OpenStruct
. Rails通过
OpenStruct
实现这OpenStruct
。 To use it, you can do: 要使用它,您可以:
@foo = ActiveSupport::JSON.decode(params[:serialized]).symbolize_keys
obj = OpenStruct.new(@foo)
obj.key #=> {"subkey1"=>"value", "subkey2"=>"value"}
But again, OpenStruct creates the object till one level for accessing with .key
instead of ':key'. 但同样,OpenStruct创建对象直到一个级别,用于访问
.key
而不是':key'。 To aid this, we have Recursive OpenStruct , which does the job perfectly. 为了解决这个问题,我们提供了Recursive OpenStruct ,它可以完美地完成工作。
This is the way, I personally feel, you should work in Rails in scenario like this(if arrives). 这是我个人觉得你应该在Rails中工作的方式(如果到达)。
Good Luck :) 祝好运 :)
First of all, :key and :"key" are two ways to express the exact same thing. 首先,:key和:“key”是表达完全相同的两种方式。 In fact if you do:
事实上,如果你这样做:
> :key == :"key"
=> true
so given a hash such as 所以给出一个哈希如
h = {:"key" => "value"}
h[:key]
=> "value"
Secondly, if you have nested hashes, you don't only want to symbolize the keys manually, you also want to symbolize the keys in the values 其次,如果你有嵌套的哈希,你不仅要手动符号化键,还要在值中符号化键
Hash[params[:serialized].symbolized_keys.map{ |k, v| [k.to_sym, v.symbolize_keys] }]
Of course, you need something more elaborate if you have more than one level of 'nestesness' 当然,如果你有不止一个级别的'nestesness',你需要更精细的东西
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.