Ruby on rails Ruby JSON解析更改哈希键

Ruby on rails Ruby JSON解析更改哈希键,ruby-on-rails,ruby,json,hash,Ruby On Rails,Ruby,Json,Hash,假设我有这个散列: { :info => [ { :from => "Ryan Bates", :message => "sup bra", :time => "04:35 AM" } ] } 我可以通过执行hash[:info]来调用info数组 现在,当我将其转换为JSON(JSON.generate)并对其进行解析(JSON.parse)时,我得到以下哈希值: { "info" =>

假设我有这个散列:

{
  :info => [
    {
        :from => "Ryan Bates",
        :message => "sup bra",
        :time => "04:35 AM"
    }
  ]
}
我可以通过执行
hash[:info]
来调用info数组

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

{
  "info" => [
    {
        "from" => "Ryan Bates",
        "message" => "sup bra",
        "time" => "04:35 AM"
    }
  ]
}
现在,如果我使用
hash[:info]
它将返回
nil
,但如果我使用
hash[“info”]
则不会返回


为什么会这样?还有什么方法可以修复这种不兼容性(除了从一开始就使用字符串键之外)?

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

但是,就为了它,这里是对这个问题的回答,以前有人问过这个问题:


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

通过使用
symbol\u names
选项,可以告诉解析器使用符号而不是字符串

例如:

参考:

  • 使用ActiveSupport::JSON.decode,可以更轻松地交换JSON解析器
  • 使用ActiveSupport::JSON.decode(my_JSON,symbol_names:true)
  • 这将递归地表示散列中的所有键


    (在ruby 2.0上确认)

    我通过对其调用with_冷漠_访问方法解决了类似的问题

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

    s = "{\"foo\":{\"bar\":\"cool\"}}"
    
    现在我可以用JSON类解析数据并将其分配给h

    h = JSON.parse(s).with_indifferent_access
    
    这将生成一个可以接受字符串或符号作为键的哈希

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

    你不能像这样使用这个选项

    ActiveSupport::JSON.decode(str\u JSON,symbol\u names:true)

    在Rails 4.1或更高版本中,
    ActiveSupport::JSON.decode
    不再接受 MultiJSON的选项哈希。MultiJSON已到了生命的尽头 已被删除

    你可以用它来处理它。 警告:它仅适用于解析为哈希的JSON字符串

    ActiveSupport::JSON.decode(str_json).symbolize_keys
    

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

    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"}
    

    谢谢你的链接,但正如你所说的,我将只使用字符串作为键,我认为它是:symbol_keys now()@Boushley:No,它仍然是
    symbol_names
    。我的答案引用了Ruby标准库附带的JSON引擎。您正在引用第三方gem。是否在rails 4.1中删除了?状态选项支持removedIs
    ,通过Rails生态系统中的某个东西将访问添加到
    Hash
    。@标记您是正确的。这里有一个链接
    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"}