2016-01-21 64 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自動收集所有的實例變量。不過,我不鼓勵這種方法,因爲您最終可能會序列化您不想共享的敏感屬性(如密碼)。

相關問題