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

时间:2013-04-29 15:31:06

标签: ruby-on-rails ruby json

我的控制器在params中收到一个JSON字符串,如下所示:

{"serialized"=>"{\"key\":{\"subkey1\":"value",\"subkey2\":"value"}"}

在我的控制器中,我尝试以下操作:

JSON.parse(params[:serialized], symbolize_names: true)

返回:

{:"key"=>{:subkey1=>"value", :subkey2=>"value"}

所有嵌套的子键都是符号化的;密钥以奇怪的方式进行符号化,因此它不响应 hash [key] ,而是响应 hash [“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

UPD 删除了最后一行(我怎么可能修复它,因为我需要我的哈希来回答哈希[键] 而不是哈希[“键”] 。)所以问题看起来不那么务实,更具理论性。

4 个答案:

答案 0 :(得分:2)

试试rails console。

require 'json'
string = {"serialized"=>"{\"key\":{\"subkey1\":"value",\"subkey2\":"value"}"}
hash = JSON.parse string

答案 1 :(得分:1)

我同意@boulder上面所说的话。但是,因为Hash[params[:serialized].symbolized_keys.map{ |k, v| [k.to_sym, v.symbolize_keys] }]用于符号化直到1级。我永远不会真的为此而努力。

这可能与您要求的不同,但在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(如果到达)。

祝你好运:)

答案 2 :(得分:0)

首先,: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] }]

当然,如果你有不止一个级别的'nestesness',你需要更精细的东西

答案 3 :(得分:0)

旧主题,但是对于那些可能落在上面的主题,Rails提供了List<MyObjects> objects = /* omitted */; List<MyObjects> filteredObjects = objects.stream() .peek(MyObjects::setNextSycDateWithSomeLogic()) .filter(obj -> Objects.nonNull(obj.getNextSyncDate()) && obj.getNextSyncDate().before(new Date())) .collect(Collectors.toList()); 方法,该方法似乎在解析json之后完全满足op的需求:

deep_symbolize_keys

来源:https://apidock.com/rails/Hash/deep_symbolize_keys