简体   繁体   English

Ruby / Rails - JSON.parse / JSON.decode问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM