2016-05-02 16 views
0

私はこのコードを持っている:Ruby JSONを使用してクラスのインスタンスを保存するにはどうすればよいですか?

require 'json' 

class A 
    attr_accessor :a, :b, :c 
    def initialize(a, b, c) 
    @a = a, @b = b, @c = c 
    end 
end 

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

puts "\n\nJSON: " 
puts a.to_json 


puts "\n\nJSON.pretty_generate: " 
puts JSON.pretty_generate(a) 

出力は本当にdissapointingです:

#<A:0x000000019f4678 @b="a", @c=[1, 2, 3], @a=[1, "a", [1, 2, 3]]> 


JSON: 
"#<A:0x000000019f4678>" 


JSON pretty generate: 
blahblah.rb:285:in `generate': only generation of JSON objects 
or arrays allowed (JSON::GeneratorError) 

クラスのインスタンスとJSONオブジェクトの違いは何ですか? JSONオブジェクトにクラスのインスタンスを変換するには?

+0

*データ*あり*コード*があります。 JSONはデータを交換する形式ですが、クラスはコードです。 – Stefan

+0

あなたは「クラス」と言うとき、「クラスのインスタンス」を意味しますか? –

+0

はい、クラスのインスタンスを意味します。 –

答えて

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 

が、私はコンストラクタで各属性の書き込み可能なメソッドを呼び出すために送って使用しています。このビット説明するために、これはのparamsを通過し、インスタンス変数の値を設定します。

次に、属性メソッドはATTRS定数配列を使用して、このインスタンスのプロパティのオブジェクトマップのみを作成します。だから私たちはそれをシリアル化し、新しいインスタンスを作るためにデシリアライズします。

これはレールの仕組みとほとんど同じですが、ActiveRecordは従来のアクセサ上のプロパティを格納するための属性ハッシュを使用します。

+0

クラスAにさらにクラスを含むクラスBの配列が含まれている場合、これがどのように機能するかわかりません。 ECMASCRIPT 6はクラスをサポートしていますが、JSONはまだサポートしていませんか?それは本当に私を混乱させています。 –

+0

JSONはコードのシリアル化ではなく、データ形式です。 JSONは関数をシリアル化できません。理想的には、メソッドや関数をシリアライズしたり保存したりしないでください。どこかのクライアントでそのデータを持っていて、バックエンドが更新された場合はどうでしょうか?格納されたオブジェクトは、もはや期待どおりに動作しません。 – agmcleod

4

一つはRuby classです:

ウィキペディアから:他のJSON object

In object-oriented programming, a class is an extensible program-code-template for creating objects, providing initial values for state (member variables) and implementations of behavior (member functions or methods).

JSON: JavaScript Object Notation.

JSON is a syntax for storing and exchanging data.

JSON is an easier-to-use alternative to XML.

だから、これは通常のサーバーからデータを提供するためによく知られた問題であり、 Webブラウザを使用する場合は、DAataのJSON表現を送信します。通常は、このデータを解析してサーバーで作業するために、Rubyオブジェクトに渡します。あなたは単に、あなたが文字列を解析することはできません、オブジェクト、このためには、あなたがクラス内

irb(main):046:0> JSON.pretty_generate("calimero") 
JSON::GeneratorError: only generation of JSON objects or arrays allowed 
    from /Users/toni/.rvm/gems/[email protected]/gems/json-1.8.3/lib/json/common.rb:285:in `generate' 
    from /Users/toni/.rvm/gems/[email protected]/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]" 

の方法のto_jsonを追加することができJSONに解析することができます

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

エラーに私はVirtusの宝石を使用することをお勧めします。これはオブジェクトのタイプを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> 
3

How to convert instance of class to JSON object?

RubyのJSONの実装は、カスタムオブジェクトをデシリアライズ/シリアライズすることができますが、詳細を提供しなければならない、すなわち、そのJSON表現

からオブジェクトを作成します

  1. あなたのオブジェクトからJSON表現を返しto_jsonインスタンスメソッドと
  2. 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"です。このオプションを指定しない

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

    、パーサはA.json_createを起動し、代わりにプレーンなハッシュを返していません:それはあなたがcreate_additions: trueを渡す場合parseによって認識される特殊な識別子です

    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 
        ] 
    } 
    
関連する問題