Ruby JSON解析更改哈希键


67

可以说我有这个哈希:

{
  :info => [
    {
        :from => "Ryan Bates",
        :message => "sup bra",
        :time => "04:35 AM"
    }
  ]
}

我可以通过这样做来调用信息数组hash[:info]

现在,当我将其转换为JSON(JSON.generate),然后对其进行解析(JSON.parse)时,将得到以下哈希值:

{
  "info" => [
    {
        "from" => "Ryan Bates",
        "message" => "sup bra",
        "time" => "04:35 AM"
    }
  ]
}

现在,如果使用hash[:info]nil,它将返回,但是如果使用,则不会hash["info"]

为什么是这样?而且是否有任何方法可以解决这种不兼容问题(除了从一开始就使用字符串键)?

Answers:


24

简而言之,没有。以这种方式考虑,将符号存储在JSON中与将字符串存储在JSON中相同。因此,在解析JSON字符串时,您可能无法区分两者。您当然可以将字符串键转换回符号,或者实际上甚至可以构建一个类来与JSON交互,这可以自动完成此操作,但是我建议仅使用字符串。

但是,仅出于此目的,这是上次被问到此问题的答案:

将json格式的键值对转换为以符号为键的ruby hash的最佳方法是什么?

ActiveSupport :: JSON解码散列丢失符号

或者也许是HashWithIndifferentAccess


感谢您提供的链接,但是就像您说的,我将只使用字符串作为键
LanguagesNamedAfterCofee

145

JSON生成器将符号转换为字符串,因为JSON不支持符号。由于JSON键都是字符串,因此默认情况下,解析JSON文档将生成带有字符串键的Ruby哈希。

通过使用该symbolize_names选项,您可以告诉解析器使用符号而不是字符串。

例:

original_hash = {:info => [{:from => "Ryan Bates", :message => "sup bra", :time => "04:35 AM"}]}
serialized = JSON.generate(original_hash)
new_hash = JSON.parse(serialized, {:symbolize_names => true})

new_hash[:info]
 #=> [{:from=>"Ryan Bates", :message=>"sup bra", :time=>"04:35 AM"}]

参考:http : //www.ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html#method-i-parse


我认为现在是:symbolize_keys(rubydoc.info/gems/multi_json/1.3.2/MultiJson
Boushley,

12
@Boushley:不,还是symbolize_names。我的答案引用了Ruby标准库附带的JSON引擎。您引用的是第三方gem。
wyattisimo

6

我通过调用with_indifferent_access方法解决了类似的问题

这里我有一个json字符串,我们可以将其分配给变量s

s = "{\"foo\":{\"bar\":\"cool\"}}"

所以现在我可以使用JSON类解析数据并将其分配给h

h = JSON.parse(s).with_indifferent_access

这将产生一个可以接受字符串或符号作为键的哈希值

h[:foo]["bar"]
  #=> "cool"

是通过Rails生态系统中的某种东西with_indifferent_access添加的Hash
2016年

1
@标记您是正确的。这是一个链接api.rubyonrails.org/v4.2.5/classes/ActiveSupport/…–
aaron.v


2

可以修改哈希中的所有键,以将它们从字符串转换为符号:

symbol_hash = Hash[obj.map{ |k,v| [k.to_sym, v] }]

puts symbol_hash[:info]
# => {"from"=>"Ryan Bates", "message"=>"sup bra", "time"=>"04:35 AM"}

不幸的是,这不适用于嵌套在数组中的哈希。但是,您可以编写一些递归方法来转换所有哈希键:

def symbolize_keys(obj)
  #puts obj.class # Useful for debugging
  return obj.collect { |a| symbolize_keys(a) } if obj.is_a?(Array)
  return obj unless obj.is_a?(Hash)
  return Hash[obj.map{ |k,v| [k.to_sym, symbolize_keys(v)] }]
end

symbol_hash = symbolize_keys(hash)
puts symbol_hash[:info]
# => {:from=>"Ryan Bates", :message=>"sup bra", :time=>"04:35 AM"}

0

您不能像这样使用该选项

ActiveSupport::JSON.decode(str_json, symbolize_names: true)

在Rails 4.1或更高版本中,ActiveSupport::JSON.decode不再接受MultiJSON的选项哈希。MultiJSON已到使用寿命,并且已被删除。

您可以使用symbolize_keys进行处理。警告:仅适用于解析为哈希的JSON字符串。

ActiveSupport::JSON.decode(str_json).symbolize_keys
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.