我正在尝试将一个简单的结构序列化为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>'
答案 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
方法,可用于将该结构转换为Hash
,Hash
为({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\"}"