【问题标题】:How to serialize/deserialize ruby hashes/structs with objects as keys to json如何使用对象作为 json 的键来序列化/反序列化 ruby​​ 哈希/结构
【发布时间】:2019-02-19 08:40:20
【问题描述】:

我想将 ruby​​ 中的嵌套数据结构转储到 json(我知道 Marshal 模块,但我需要标准格式)并能够再次加载/解析数据结构。 Catch:我使用结构(或更简单的例子:哈希)作为哈希的键。示例:

require 'json'
h = {{hello: 123} => 123}
JSON.parse(JSON.generate(h)) #=> {"{:hello=>123}"=>123}

所以问题是,JSON.generate(h) 将键 {:hello=>123} 序列化为字符串,当我再次解析结果时,它仍然是字符串。

如何解决这个问题并在生成/解析后恢复原始结构?

【问题讨论】:

标签: json ruby hashmap


【解决方案1】:

正如 mudasobwa 已经指出的那样,YAML 是一个很好的工具:允许您还存储自定义类对象:

require 'yaml'

class MyCaptain
  attr_accessor :name, :ship
  def initialize(name, ship)
    @name = name
    @ship = ship
  end
end

kirk = MyCaptain.new('James T. Kirk', 'USS Enterprise NCC-1701')
picard = MyCaptain.new('Jean-Luc Picard', 'Enterprise NCC-1701D')

captains = [kirk, picard]

File.open("my_captains.yml","w") do |file|
   file.write captains.to_yaml
end 

p YAML.load_file('my_captains.yml')

#=> [#<MyCaptain:0x007f889d0973b0 @name="James T. Kirk", @ship="USS Enterprise NCC-1701">, #<MyCaptain:0x007f889d096b40 @name="Jean-Luc Picard", @ship="Enterprise NCC-1701D">]

【讨论】:

    【解决方案2】:

    我需要一个标准格式

    YAML 是一种标准格式,在这里就足够了:

    ▶ h = {{hello: 123} => 123}
    #⇒ {{:hello=>123}=>123}
    ▶ YAML.dump h
    #⇒ "---\n? :hello: 123\n: 123\n"
    ▶ YAML.load _
    #⇒ {{:hello=>123}=>123}
    

    【讨论】:

      【解决方案3】:

      JSON 只允许字符串作为对象键。出于这个原因,to_s 会为所有键调用。

      您将有以下选项来解决您的问题:

      1. 最好的选择是更改数据结构,使其可以正确序列化为 JSON。

      2. 您必须自己处理字符串化的密钥。当转换为可以使用Kernel#eval 转换的字符串时,哈希会产生完全有效的Ruby 语法,例如Andrey Deineko suggested in the comments

        result = json.transform_keys { |key| eval(key) }
               # json.transform_keys(&method(:eval)) is the same as the above.
        

        Hash#transform_keys 方法相对较新(自 Ruby 2.5.0 起可用),目前可能不在您的开发环境中。如果需要,您可以将其替换为简单的 Enumerable#map

        result = json.map { |k, v| [eval(k), v] }.to_h
        

        注意:如果传入的 JSON 包含任何用户生成的内容,我强烈建议您不要使用 eval,因为您可能允许用户在您的服务器上执行代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-28
        • 2019-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-28
        • 1970-01-01
        相关资源
        最近更新 更多