Ruby如何用JSON保存类的实例?

时间:2016-05-02 13:14:24

标签: ruby json

我有这段代码:

string

输出真的令人失望:

string

类和JSON对象之间的区别是什么? 如何将类的实例转换为JSON对象?

3 个答案:

答案 0 :(得分:4)

有一件事是Ruby class

来自维基百科的

  

在面向对象的编程中,类是可扩展的   程序代码模板,用于创建对象,提供初始值   for state(成员变量)和行为的实现(成员   功能或方法)。

另一个JSON object

  

JSON:JavaScript Object Notation。

     

JSON是一种用于存储和交换数据的语法。

     

JSON是一种易于使用的XML替代方法。

因此,这是一个众所周知的问题,通常用于从服务器向Web浏览器提供数据,您通常会发送DATA的JSON表示,以便在服务器中将此数据解析为ruby对象。

错误:

http://apidock.com/ruby/JSON/pretty_generate

你只能解析Json的简单对象,你不能解析String,为此你可以在类A中添加方法to_json

irb(main):046:0> JSON.pretty_generate("calimero")
JSON::GeneratorError: only generation of JSON objects or arrays allowed
    from /Users/toni/.rvm/gems/ruby-2.2.3@stackoverflow/gems/json-1.8.3/lib/json/common.rb:285:in `generate'
    from /Users/toni/.rvm/gems/ruby-2.2.3@stackoverflow/gems/json-1.8.3/lib/json/common.rb:285:in `pretty_generate'
    from (irb):59
    from /Users/toni/.rvm/rubies/ruby-2.2.3/bin/irb:11:in `<main>'
irb(main):060:0> JSON.pretty_generate([1,2,3])
=> "[\n  1,\n  2,\n  3\n]"

我建议你使用Virtus gem,这澄清了你要解析为JSON的对象的类型,对我来说,知道你转换为JSON的是什么以及你期望的数据是一个好习惯

require 'virtus'
require 'json'

class A
  include Virtus.model

  attr_accessor :a, :b, :c

  attribute :a, Integer
  attribute :b, String
  attribute :c, Array[Integer]

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

end



irb(main):039:0> a = A.new(1, "a", [1, 2, 3])
=> #<A:0x007fc391882ac8 @b="a", @c=[1, 2, 3], @a=[1, "a", [1, 2, 3]]>
irb(main):040:0> a.attributes
=> {:a=>[1, "a", [1, 2, 3]], :b=>"a", :c=>[1, 2, 3]}
irb(main):053:0> require 'json'
=> true
irb(main):085:0> a.attributes.to_json
=> "{\"a\":[1,\"a\",[1,2,3]],\"b\":\"a\",\"c\":[1,2,3]}"
irb(main):096:0> 

答案 1 :(得分:3)

  

如何将类的实例转换为JSON对象?

Ruby的JSON实现可以序列化/反序列化自定义对象,但是你必须提供详细信息,即

  1. 一个to_json实例方法,它从对象和
  2. 返回JSON表示
  3. 从{JSON表示
  4. 创建对象的json_create类方法

    以下是使用您的课程的示例:

    require 'json'
    
    class A
      attr_accessor :a, :b, :c
    
      def initialize(a, b, c)
        @a, @b, @c = a, b, c
      end
    
      def to_json(*args)
        {
          JSON.create_id => self.class.name,
          'a' => a,
          'b' => b,
          'c' => c
        }.to_json(*args)
      end
    
      def self.json_create(h)
        new(h['a'], h['b'], h['c'])
      end
    end
    
    a = A.new(1, 'a', [1, 2, 3])
    #=> #<A:0x007f92cc8f37f0 @a=1, @b="a", @c=[1, 2, 3]>
    
    a.to_json
    #=> "{\"json_class\":\"A\",\"a\":1,\"b\":\"a\",\"c\":[1,2,3]}"
    

    JSON.create_id默认为字符串"json_class"。如果您通过create_additions: true,它是parse可识别的特殊标识符:

    JSON.parse(a.to_json, create_additions: true)
    #<A:0x007ff59c0f2578 @a=1, @b="a", @c=[1, 2, 3]>
    

    如果没有此选项,解析器不会调用A.json_create并返回普通哈希:

    JSON.parse(a.to_json)
    #=> {"json_class"=>"A", "a"=>1, "b"=>"a", "c"=>[1, 2, 3]}
    

    调用JSON.pretty_generate(a)会生成以下输出:

    {
      "json_class": "A",
      "a": 1,
      "b": "a",
      "c": [
        1,
        2,
        3
      ]
    }
    

答案 2 :(得分:0)

我会查看序列化数据,并使您的类工作,以便它可以很容易地响应属性。

require 'json'

class A
  ATTRS = [:a, :b, :c]
  attr_accessor *ATTRS
  def initialize(params)
    params.each do |k, v|
      self.send("#{k}=".to_sym, v)
    end
  end

  def attributes
    values = {}
    ATTRS.each do |key|
      values[key] = self.send(key)
    end
    values
  end
end

a = A.new(a: 1, b: "a", c: [1, 2, 3])
p a

data = a.attributes.to_json
puts data
b = A.new(JSON.parse(data))

p b

为了解释这一点,我使用send为构造函数中的每个属性调用可写方法,这将通过params并设置实例变量值。

然后,attributes方法使用ATTRS常量数组来构建仅此实例属性的对象映射。所以我们序列化它,并反序列化以创建一个新实例。

这几乎是rails的用途,尽管ActiveRecord使用属性哈希来存储传统访问器的属性。