require 'spec_helper' describe Jsonify::Builder do let(:json) { Jsonify::Builder.new } describe 'class methods' do it '#compile should compile' do Jsonify::Builder.compile do |j| j.foo 'bar' end.should == '{"foo":"bar"}' end it '#pretty should be pretty' do pretty_results = < true) json.stack << FooBar.new lambda{ json.compile! }.should raise_error(MultiJson::DecodeError) end end describe 'unicode characters' do it 'should properly encode' do json = Jsonify::Builder.new(:verify => true) json.foo 'bar'.concat(16) lambda { json.compile! }.should_not raise_error end end describe "pretty printing" do it "should not be pretty by default" do json.foo do json.bar 'baz' end non_pretty_results = '{"foo":{"bar":"baz"}}' json.compile!.should == non_pretty_results end it "should be pretty when asked for" do json = Jsonify::Builder.new(:format => :pretty) json.foo do json.bar 'baz' end pretty_results = < :bar} json << {:go => :far} json.compile!.should == '[{"foo":"bar"},{"go":"far"}]' end end describe 'objects' do it 'simple object should work' do json.foo :bar json.go :far expected = '{"foo":"bar","go":"far"}' MultiJson.load(json.compile!).should == MultiJson.load(expected) end it 'should handle arrays' do json[1] = [2, 3] json[4] = 5 MultiJson.load(json.compile!).should == MultiJson.load('{"1":[2,3],"4":5}') end end describe "attributes!" do it "should allow create object with attributes of another object" do object = stub(:id => 1, :name => 'foo') json.attributes!(object, :id, :name) MultiJson.load(json.compile!).should == {'id' => 1, 'name' => 'foo'} end end describe 'using blocks' do it 'should allow names with spaces using tag!' do json.tag!("foo foo") do json.tag!("bar bar") do json.tag!('buzz buzz','goo goo') end end expected = '{"foo foo":{"bar bar":{"buzz buzz":"goo goo"}}}' MultiJson.load(json.compile!).should == MultiJson.load(expected) end it 'complex hash' do json.foo do json.bar do json.baz 'goo' end end json.compile!.should == '{"foo":{"bar":{"baz":"goo"}}}' end it 'simple hash' do json.foo do json.baz :goo end json.compile!.should == '{"foo":{"baz":"goo"}}' end it 'hash with array' do json.foo do json << 1 json << 2 end json.compile!.should == '{"foo":[1,2]}' end it 'hash with array by iteration' do ary = [1,2,3] json.foo do ary.each do |n| json << (n * 2) end end json.compile!.should == '{"foo":[2,4,6]}' end it 'simple array with object' do json << 1 json << {:foo => :bar} json.compile!.should == '[1,{"foo":"bar"}]' end it 'simple array with object via method_missing' do json << 1 json << 2 json.foo :bar json.compile!.should == "[1,2,{\"foo\":\"bar\"}]" end it 'complex hash with array' do json.foo do json.bar do json.baz 'goo' json.years do json << 2011 json << 2012 end end end expected = "{\"foo\":{\"bar\":{\"baz\":\"goo\",\"years\":[2011,2012]}}}" MultiJson.load(json.compile!).should == MultiJson.load(expected) end end describe 'without blocks' do describe 'complex array' do it 'should work' do json.bar [1,2,{:foo => 'goo'}] expected = "{\"bar\":[1,2,{\"foo\":\"goo\"}]}" MultiJson.load(json.compile!).should == MultiJson.load(expected) end end describe 'object with null' do it 'should handle missing argument' do json.foo json.compile!.should == '{"foo":null}' end end end describe 'super complex example' do let(:links) { link_class = Struct.new(:url,:type) [ link_class.new('example.com', 'self'), link_class.new('foo.com', 'parent') ] } it 'should work using arrays' do json.result do json.person do json.fname 'George' json.lname 'Burdell' end json.links(links) do |link| json.href link.url json.rel link.type end end expected = "{\"result\":{\"person\":{\"fname\":\"George\",\"lname\":\"Burdell\"},\"links\":[{\"href\":\"example.com\",\"rel\":\"self\"},{\"href\":\"foo.com\",\"rel\":\"parent\"}]}}" MultiJson.load(json.compile!).should == MultiJson.load(expected) end end describe 'ingest!' do context 'a json object' do let(:json_string) { '{"my girl":"Friday","my daughter":"Wednesday"}' } context 'into' do it 'nothing -- should replace it' do json.ingest! json_string MultiJson.load(json.compile!).should == MultiJson.load(json_string) end it 'json object -- should merge' do json["my boy"] = "Monday" json["my girl"] = "Sunday" json.ingest! json_string expected = '{"my boy":"Monday","my girl":"Friday","my daughter":"Wednesday"}' MultiJson.load(json.compile!).should == MultiJson.load(expected) end it 'json array -- should add' do json << 1 << 2 json.ingest! json_string expected = '[1,2,{"my girl":"Friday","my daughter":"Wednesday"}]' MultiJson.load(json.compile!).should == MultiJson.load(expected) end end end context 'a json array' do let(:json_string) { '[1,2,3]' } context 'into' do it 'nothing -- should replace it' do json.ingest! json_string MultiJson.load(json.compile!).should == MultiJson.load(json_string) end it 'json object -- should raise error' do json["my boy"] = "Monday" json["my girl"] = "Sunday" lambda{ json.ingest! json_string }.should raise_error( ArgumentError ) end it 'json array -- should add' do json << 1 << 2 json.ingest! json_string expected = '[1,2,[1,2,3]]' MultiJson.load(json.compile!).should == MultiJson.load(expected) end end end end describe 'with new array style' do it 'should work' do results =[ {:id => 1, :kids => [{:id => 'a'},{:id => 'b'}]}, {:id => 2, :kids => [{:id => 'c'},{:id => 'd'}]}, ] json.results(results) do |result| json.id result[:id] json.children(result[:kids]) do |kid| json.id kid[:id] end end expected = '{"results":[{"id":1,"children":[{"id":"a"},{"id":"b"}]},{"id":2,"children":[{"id":"c"},{"id":"d"}]}]}' MultiJson.load(json.compile!).should == MultiJson.load(expected) end it 'simple append' do json.letters('a'..'c') do |letter| json << letter.upcase end expected = '{"letters":["A","B","C"]}' MultiJson.load(json.compile!).should == MultiJson.load(expected) end end describe 'array!' do it 'allow creating array from root' do json.array!([1, 2, 3]) do |number| json.id number json.times2 number * 2 end MultiJson.load(json.compile!).should == [ {'id' => 1, 'times2' => 2}, {'id' => 2, 'times2' => 4}, {'id' => 3, 'times2' => 6}, ] end end end