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

ez.*_*ez. 99 ruby json ruby-on-rails

我想知道将符号作为键将json格式的键值对转换为ruby hash的最佳方法是什么:示例:

{ 'user': { 'name': 'foo', 'age': 40, 'location': { 'city' : 'bar', 'state': 'ca' } } }
==> 
{ :user=>{ :name => 'foo', :age =>'40', :location=>{ :city => 'bar', :state=>'ca' } } }
Run Code Online (Sandbox Code Playgroud)

是否有辅助方法可以做到这一点?

小智 247

在解析json字符串时使用json gem,您可以传入symbolize_names选项.请看这里:http://flori.github.com/json/doc/index.html(在解析下查看)

例如:

>> s ="{\"akey\":\"one\",\"bkey\":\"two\"}"
>> JSON.parse(s,:symbolize_names => true)
=> {:akey=>"one", :bkey=>"two"} 
Run Code Online (Sandbox Code Playgroud)

  • @Lukas:`symbolize_keys`是一个Rails的东西. (5认同)
  • 顺便说一下,R​​uby 1.9包含了这个库. (4认同)

小智 19

Leventix,谢谢你的回答.

Marshal.load(Marshal.dump(H))方法可能有各种方法最诚信,因为它保留了原始密钥类型递归.

这很重要,如果你有一个混合了字符串和符号键的嵌套哈希,并且你想在解码时保留该混合(例如,如果你的哈希包含你自己的自定义对象以及高度复杂/嵌套的第三个,那么这可能会发生 - 无论出于何种原因你无法操纵/转换其键的对象,如项目时间约束).

例如:

h = {
      :youtube => {
                    :search   => 'daffy',                 # nested symbol key
                    'history' => ['goofy', 'mickey']      # nested string key
                  }
    }
Run Code Online (Sandbox Code Playgroud)

方法1:JSON.parse - 递归地符号化所有键=>不保留原始混合

JSON.parse( h.to_json, {:symbolize_names => true} )
  => { :youtube => { :search=> "daffy", :history => ["goofy", "mickey"] } } 
Run Code Online (Sandbox Code Playgroud)

方法2:ActiveSupport :: JSON.decode - 仅表示顶级键=>不保留原始混音

ActiveSupport::JSON.decode( ActiveSupport::JSON.encode(h) ).symbolize_keys
  => { :youtube => { "search" => "daffy", "history" => ["goofy", "mickey"] } }
Run Code Online (Sandbox Code Playgroud)

方法3:Marshal.load - 在嵌套键中保留原始字符串/符号混合.完善!

Marshal.load( Marshal.dump(h) )
  => { :youtube => { :search => "daffy", "history" => ["goofy", "mickey"] } }
Run Code Online (Sandbox Code Playgroud)

除非有一个我不知道的缺点,否则我认为方法3是要走的路.

干杯

  • 这里不能保证你能控制另一方,所以我相信你必须坚持使用JSON格式.如果你完全控制双方,那么Marshal确实是一个很好的格式,但它不适合通用序列化. (2认同)

mad*_*lep 5

没有任何内置的功能,但使用JSON gem编写代码并不难.symbolize_keys如果您正在使用它,则Rails中内置了一种方法,但这并不像您需要的那样以递归方式对符号进行符号化.

require 'json'

def json_to_sym_hash(json)
  json.gsub!('\'', '"')
  parsed = JSON.parse(json)
  symbolize_keys(parsed)
end

def symbolize_keys(hash)
  hash.inject({}){|new_hash, key_value|
    key, value = key_value
    value = symbolize_keys(value) if value.is_a?(Hash)
    new_hash[key.to_sym] = value
    new_hash
  }
end
Run Code Online (Sandbox Code Playgroud)

正如Leventix所说,JSON gem只处理双引号字符串(技术上是正确的 - JSON应该用双引号格式化).在尝试解析之前,这段代码将清除它.


Lev*_*tix 1

当然,有一个json gem,但它只处理双引号。

  • 那是因为 JSON 无法表示符号。您可以使用:`Marshal.load(Marshal.dump([:a]))` 代替。 (2认同)