What is a good practice to create a JSON string of one object (object of
class A) containing an array of objects (objects of class B)? I am
particularly interessted in the implementation of class's A to_json
method.
Assuming class A looks as follows:
class A
attr_accessor :items
def initialize()
@items = Array.new
end
def to_json(*a)
?SECRET OF THE DAY?
end
end
and class B:
class B
def to_json(*a)
{"class B" => "class B"}.to_json(*a)
end
end
The best solution I got so far is:
def to_json(*a)
json = Array.new
@items.each do |item|
json << item.to_json(*a)
end
{"class A" => json}.to_json(*a)
end
Assuming there is only one item in array of an object of class A, the
resulting JSON string looks as follows:
{"class A":["{\"class B\":\"class B\"}"]}
I also tried:
def to_json(*a)
{"class A" => @items}.to_json(*a)
end
But it results in IOError exception in class A, saying to_json "not
opened for reading"...
I am sure we can do better?
···
--
Posted via http://www.ruby-forum.com/.
But it results in IOError exception in class A, saying to_json "not
opened for reading"...
I am sure we can do better?
I think it would be much better to make the class an attribute of the
JSON object, not build a new JSON object of {class => {attributes}}
If you look at the tests/ directory of the json or json_pure gem, you'll
see that they use 'json_class' for this purpose. e.g.
class A
def initialize(a)
@a = a
end
attr_reader :a
def ==(other)
a == other.a
end
def self.json_create(object)
new(*object['args'])
end
def to_json(*args)
{
'json_class' => self.class.name,
'args' => [ @a ],
}.to_json(*args)
end
end
The use of the 'args' element (being the array of arguments to #new) is
fairly ugly. I would rather expose the instance variables as members of
the JSON object:
class A
def initialize(a)
@a = a
end
attr_reader :a
def self.json_create(object)
new(object['a'])
end
def to_json(*args)
{
'json_class' => self.class.name,
'a' => @a,
}.to_json(*args)
end
end
a1 = A.new([123, 456])
puts a1.inspect
str = a1.to_json
puts str
a2 = JSON.parse(str)
puts a2.inspect
HTH,
Brian.
···
--
Posted via http://www.ruby-forum.com/\.
@Brian: Both approaches you proposed result in IOError exception in
class A, saying to_json "not opened for reading".
Besides adding a class attribute, both approaches are actually similar
to the second I mentioned...
···
--
Posted via http://www.ruby-forum.com/.
And here is a working example for your code where class A includes
instances of class B:
$ cat ert2.rb
require 'rubygems'
require 'json'
class A
attr_accessor :items
def initialize()
@items = Array.new
end
def to_json(*a)
{
"json_class" => self.class.name,
"items" => @items,
}.to_json(*a)
end
end
class B
def to_json(*a)
{
"json_class" => self.class.name,
}.to_json(*a)
end
end
a = A.new
a.items << B.new
a.items << B.new
puts a.to_json
$ ruby ert2.rb
{"items":[{"json_class":"B"},{"json_class":"B"}],"json_class":"A"}
···
--
Posted via http://www.ruby-forum.com/.
Running "ert2.rb" in console worked as expected.
I want to use to_json capability within a rails project. In my project,
I created class A and B as well as a controller to call the to_json
method. I got:
{"json_class":"A","items":[{},{}]}
After that, I reinstalled json and json_pure, using version 1.5.1 of
both now.
Now it works as expected... @Thanks to Brian
Rails 3.0.3
ruby 1.9.2p136 (2010-12-25 revision 30365) [i386-darwin9.8.0]
json 1.5.1
json_pure 1.5.1
So, reinstalling/upgrading json libs might solve the problem...
···
--
Posted via http://www.ruby-forum.com/.
Matthias S. wrote in post #980645:
@Brian: Both approaches you proposed result in IOError exception in
class A, saying to_json "not opened for reading".
Can you paste the *exact* exception you see, and the exact code which
triggers it? Plus details of the platform you are on.
It works for me:
$ ruby -v
ruby 1.8.7 (2010-06-23 patchlevel 299) [x86_64-linux]
$ ruby ert.rb
#<A:0x7f23333ad7e0 @a=[123, 456]>
{"a":[123,456],"json_class":"A"}
#<A:0x7f23333a7598 @a=[123, 456]>
That's running the code I posted, just with the addition of
require 'rubygems'
require 'json' # also works with require 'json/pure'
at the top. I have the json-1.4.3 gem installed, and json_pure-1.4.3.
Regards,
Brian.
···
--
Posted via http://www.ruby-forum.com/\.