我有一个需要转储到json的哈希,但其中一个值是一个对象:
hash = { a: my_object }
如果我尝试使用类似MultiJson.dump(hash)
的东西来转储它,它只会序列化顶级哈希值,而不是更深层次的哈希值,所以我最终得到的是
'{"a": #<...>}'
即使对象已经有to_json,to_hash等方法,也会发生这种情况,MultiJson.dump(my_object)
工作正常。
这似乎是JSON库应该做的事情,但我猜他们没有。为什么不?他们不应该/不能有程序化的原因吗?或者我错过了什么?
编辑:
更多的搜索 - 我必须在我的初步测试中弄乱一些东西。 Oj可以使用:compat选项递归转储json:
Oj.dump(my_object, mode: :compat)
使用Oj的MultiJson默认情况下会传递此选项,因此也可以使用。虽然根据Oj的文档,我不确定为什么会这样。即使没有任何as_hash或to_json方法,它也能正常工作。
答案 0 :(得分:2)
一般来说,我会做两件事之一:
加载JSON的核心扩展:
require 'json/add/core'
我不记得为什么“添加/核心”帮助了正常的require 'json'
,但确实如此。
或者我向自定义类添加to_hash
或to_array
方法并将它们分解为哈希或数组,然后可以将其传递给JSON类以进行序列化。或者我添加to_json
方法并创建一个哈希或数组,然后to_json
,返回序列化版本:
class Foo
def initialize
@bar = 1
@baz = [1, 2, 3]
@hub = {'a' => 0, 'b' => 2}
end
def to_h
{
'bar' => @bar,
'baz' => @baz,
'hub' => @hub
}
end
def to_json
to_h.to_json
end
end
require 'json'
Foo.new.to_json # => "{\"bar\":1,\"baz\":[1,2,3],\"hub\":{\"a\":0,\"b\":2}}"
添加代码以对{String}执行from_json
,您可以将对象作为JSON发送和接收。或者将该功能添加到initialize
方法中,这样如果它看到参数的字符串,它会尝试将该字符串转换回Ruby对象,然后填充值:
class Foo
def initialize(str = nil)
if str && String === str
obj = JSON[str]
@bar, @baz, @hub = obj.values_at('bar', 'baz', 'hub')
else
@bar = 1
@baz = [1, 2, 3]
@hub = {'a' => 0, 'b' => 2}
end
end
def to_h
{
'bar' => @bar,
'baz' => @baz,
'hub' => @hub
}
end
def to_json
to_h.to_json
end
end
require 'json'
json_stream = Foo.new.to_json # !> assigned but unused variable - json_stream
new_foo = Foo.new('{"bar":3,"baz":4,"hub":{"x":8,"y":9}}')
# => #<Foo:0x007f9ed4054d60 @bar=3, @baz=4, @hub={"x"=>8, "y"=>9}>
只要JSON知道如何解开特定对象,它就会毫无困难地对其进行to_json
。对于那些它不知道的类型,很容易给它一些帮助。