2016-01-21 62 views
3

我很困惑为什么我的简单红宝石对象不转换为json。为什么我的ruby类不能转换为json?

>irb 
> 
require 'json' 

class User 
    attr_accessor :name, :age 

    def initialize(name, age) 
    @name = name 
    @age = age 
    end 
end 

u1 = User.new("a", 1) 
u2 = User.new("b", 2) 

puts u1.to_json 
"\"#<User:0x000001010e9f78>\"" 

我错过了什么?

我想将这些对象存储到数组集合中,然后将整个集合转换为json。

users = [] 
users << User.new("a", 1) 
users << User.new("b", 2) 

users.to_json 

注意:这不是使用Rails,只是普通的旧Ruby!

我想我的json是一个用户对象数组。

[ 
{"name": "john", "age": 22}, 
{"name": "john1", "age": 23} 
{"name": "john2", "age": 24} 
] 
+0

看看如何封送来自JSON的ruby结构https://github.com/ruby/ruby/blob/trunk/ext/json/lib/json/add/struct.rb,你必须写下你的'to_json'和'as_json'函数,这里有更多的例子https://github.com/ruby/ruby/tree/trunk/ext/json/lib/json/add – bjhaid

+0

我觉得这会更容易,我被宠坏了:) – Blankman

+0

它会更容易,但很难知道你想让你的json看起来像 – bjhaid

回答

0

默认情况下,不能将类设为JSON字符串。你必须有一个to_json方法在您的类,所以你可以把它继承这个类(类型class User < JSONable

class JSONable 
    def to_json 
     hash = {} 
     self.instance_variables.each do |x| 
      hash[x] = self.instance_variable_get x 
     end 
     return hash.to_json 
    end 
end 

然后,你可以调用to_json,它会正常工作。


测试:

$ irb

irb(main):001:0> require 'json' 
=> true 
irb(main):002:0> class JSONable 
irb(main):003:1>  def to_json 
irb(main):004:2>   hash = {} 
irb(main):005:2>   self.instance_variables.each do |x| 
irb(main):006:3*    hash[x] = self.instance_variable_get x 
irb(main):007:3>   end 
irb(main):008:2>   return hash.to_json 
irb(main):009:2>  end 
irb(main):010:1> end 
=> nil 
irb(main):011:0> class User < JSONable 
irb(main):012:1> attr_accessor :name, :age 
irb(main):013:1> 
irb(main):014:1* def initialize(name, age) 
irb(main):015:2>  @name = name 
irb(main):016:2>  @age = age 
irb(main):017:2> end 
irb(main):018:1> end 
=> nil 
irb(main):019:0> 
irb(main):020:0* user = User.new("hi",3) 
=> #<User:0x007fd6c8af0a90 @name="hi", @age=3> 
irb(main):021:0> puts user.to_json 
{"@name":"hi","@age":3} 
+0

这个JSONable可以做成一个模块,所以我可以混合它而不是继承? – Blankman

+0

我不确定,但我会保留它作为一个类,以便您可以更轻松地修改它。 – AMACB

+0

@Blankman你应该可以把它改成一个模块并且方便地混合使用 – bjhaid

1

to_json默认的实现是很简单,显然不是做你所期待的。这是预料之中的:您需要编写代码向解释器解释您希望程序的行为。

提供to_jsonas_json方法是一种常见的标准。第一个后者返回JSON序列化版本的实例(通常为Hash),后者是实际的JSON输出。

class User 
    attr_accessor :name, :age 

    def initialize(name, age) 
    @name = name 
    @age = age 
    end 

    def as_json(*) 
    { name: @name, age: @age } 
    end 

    def to_json(*) 
    as_json.to_json() 
    end 
end 

下面是输出

2.3.0 :034 > u1.as_json 
=> {:name=>"a", :age=>1} 
2.3.0 :035 > puts u1.to_json 
{"name":"a","age":1} 
=> nil 

随着一点点努力,你可以改变as_json自动收集所有的实例变量。不过,我不鼓励这种方法,因为您最终可能会序列化您不想共享的敏感属性(如密码)。

相关问题