Ruby使用JSON序列化struct

时间:2015-02-04 03:39:53

标签: ruby json serialization

我正在尝试将一个简单的结构序列化为JSON,它工作正常,但是我无法从JSON创建该结构的实例。以下是我尝试这样做的方法。

require 'rubygems'
require 'json'

Person = Struct.new(:name, :age)

json = Person.new('Adam', 19).to_json
puts json

me = JSON.load(json)
puts me.name

我得到以下输出:

"#<struct Person name=\"Adam\", age=19>"
/usr/lib/ruby/1.9.1/json/common.rb:148:in `parse': 746: unexpected token at '"#<struct Person name=\"Adam\", age=19>"' (JSON::ParserError)
    from /usr/lib/ruby/1.9.1/json/common.rb:148:in `parse'
    from /usr/lib/ruby/1.9.1/json/common.rb:309:in `load'
    from why.rb:9:in `<main>'

2 个答案:

答案 0 :(得分:16)

在这种情况下,person.to_json没有按照您的预期行事。

当您require 'json'时,JSON库会在#to_json上插入一个Object方法,如果在其他地方没有提供专门的#to_json方法,则该方法是后备的。 This inserted method与在对象上调用#to_s#to_json基本相同。

如果您的Person课程在这里,#to_s会输出standard Object#to_s,默认情况下,它不会提供JSON库可解析的字符串。

但是,Struct 提供#to_h方法,可用于将该结构转换为HashHash为({1}}在要求JSON库)知道如何生成JSON可解析输出时。

如此简单地改变:

json = Person.new('Adam', 19).to_json
puts json

为:

person = Person.new('Adam', 19)
puts person.to_h.to_json

会做你期望的事。

(另外,我实际上建议您直接在#to_json课程上实施Person,因为调用#to_h#to_json会违反Law of Demeter。)

答案 1 :(得分:0)

您还可以使用to_json方法定义结构。取决于您是否愿意致电to_h.to_json。如果在一个类中仅内部调用了一次,则可能是可以接受的,并且可以忽略它。但是,如果使用该结构,则可以选择以下多次。

require 'struct'
require 'json'

MyStruct = Struct.new(:foo, :bar) do
  def to_json
    to_h.to_json
  end
end

simple_struct = MyStruct.new("hello", "world")
simple_struct.to_json

# => "{\"foo\":\"hello\",\"bar\":\"world\"}"