简体   繁体   English

Ruby中的往返JSON序列化

[英]Round-trip JSON serialization in Ruby

Suppose I have a simple class 假设我有一堂简单的课

class Person
  attr_accessor :name
  def say
    puts name
  end
end

Is there a way to serialize it to JSON and back and get instance of the same class? 有没有一种方法可以将其序列化为JSON并返回并获取同一类的实例? For example I would like to have a code like 例如,我想要一个类似的代码

p = Person.new
p.name = 'bob'
json = JSON.serialize p
# json should be smth. containing { 'name' : 'bob' } 
# and maybe some additional information required for later deserialization
p2 = JSON.deserialize
p2.say
# should output 'bob'

I tried as_json (from ActiveSupport I guess), but result is {'name': 'bob'} and obviously type information is lost and after deserialization I just have a hash, not a Person instance. 我尝试了as_json(我想是来自ActiveSupport的),但是结果是{'name':'bob'},显然类型信息丢失了,反序列化之后我只有一个哈希,而不是Person实例。

Ruby's JSON library supports the Marshal interface. Ruby的JSON库支持Marshal接口。 Short answer: you need to define #to_json and self#json_create in your class. 简短的答案:您需要在类中定义#to_jsonself#json_create

The trick is that you need to store the name of the class you want to round-trip back to in the json itself; 诀窍是您需要将要往返的类的名称存储在json本身中; the default place to do this is as the value of the key json_class and there's likely no reason to change it. 默认的位置是键json_class的值,可能没有理由更改它。

Here's a ridiculously simple example: 这是一个非常简单的例子:

require 'json'

class A
  attr_accessor :a,:b

  def initialize(a,b)
    @a = a
    @b = b
  end

  def to_json(*a)
    {
      "json_class"   => self.class.name,
      "data"         => {:a => @a, :b=>@b}
    }.to_json(*a)
  end

  def self.json_create(h)
      self.new(h["data"]["a"], h["data"]["b"])
  end

end

Then you can round-trip it with JSON.generate and JSON.load . 然后,您可以使用JSON.generateJSON.load Note that JSON.parse will not work; 请注意, JSON.parse 无法使用; it'll just give you back the expected hash. 它只会给您预期的哈希值。

[29] pry(main)> x = A.new(1,2)
=> #<A:0x007fbda457efe0 @a=1, @b=2>
[30] pry(main)> y = A.new(3,4)
=> #<A:0x007fbda456ea78 @a=3, @b=4>
[31] pry(main)> str = JSON.generate(x)
=> "{\"json_class\":\"A\",\"data\":{\"a\":1,\"b\":2}}"
[32] pry(main)> z = JSON.load(str)
=> #<A:0x007fbda43fc050 @a=1, @b=2>
[33] pry(main)> arr = [x,y,z]
=> [#<A:0x007fbda457efe0 @a=1, @b=2>, #<A:0x007fbda456ea78 @a=3, @b=4>, #<A:0x007fbda43fc050 @a=1, @b=2>]
[34] pry(main)> str = JSON.generate(arr)
=> "[{\"json_class\":\"A\",\"data\":{\"a\":1,\"b\":2}},{\"json_class\":\"A\",\"data\":{\"a\":3,\"b\":4}},{\"json_class\":\"A\",\"data\":{\"a\":1,\"b\":2}}]"
[35] pry(main)> arr2 = JSON.load(str)
=> [#<A:0x007fbda4120a48 @a=1, @b=2>, #<A:0x007fbda4120700 @a=3, @b=4>, #<A:0x007fbda4120340 @a=1, @b=2>]  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM