Skip to content

Commit 8794387

Browse files
author
Ben Rosenblum
committed
Correctly serializes nested hash elements when a root element is used with an Entity.
Previously, when a root element is used with an Entity, the presenter wraps the array of Entity object in a plain hash, and the Entities end up serialized as plain strings of the class name (i.e., {"root":["#<EntityFoo...>","#<EntityBar...>"]) The new code recursively checks for any elements of the hash that respond to serializable_hash and calls it if present.
1 parent 346fb94 commit 8794387

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

lib/grape/middleware/base.rb

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,26 @@ def decode_json(object)
110110
MultiJson.load(object)
111111
end
112112

113+
def serialize_recurse(object)
114+
if object.respond_to? :serializable_hash
115+
object.serializable_hash
116+
elsif object.kind_of?(Array) && !object.map {|o| o.respond_to? :serializable_hash }.include?(false)
117+
object.map {|o| o.serializable_hash }
118+
elsif object.kind_of?(Hash)
119+
object.inject({}) { |h,(k,v)| h[k] = serialize_recurse(v); h }
120+
else
121+
object
122+
end
123+
end
124+
113125
def encode_json(object)
114126
return object if object.is_a?(String)
115127

116-
if object.respond_to? :serializable_hash
117-
MultiJson.dump(object.serializable_hash)
118-
elsif object.kind_of?(Array) && !object.map {|o| o.respond_to? :serializable_hash }.include?(false)
119-
MultiJson.dump(object.map {|o| o.serializable_hash })
120-
elsif object.respond_to? :to_json
128+
serialized_hash = serialize_recurse(object)
129+
if (object == serialized_hash) && (object.respond_to? :to_json)
121130
object.to_json
122131
else
123-
MultiJson.dump(object)
132+
MultiJson.dump(serialized_hash)
124133
end
125134
end
126135

spec/grape/middleware/formatter_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,18 @@ def serializable_hash
4848
subject.call({'PATH_INFO' => '/somewhere', 'HTTP_ACCEPT' => 'application/json'}).last.each{|b| b.should == '{"abc":"def"}'}
4949
end
5050

51+
it 'should serialize objects that respond to #serializable_hash if there is a root element' do
52+
class SimpleExample
53+
def serializable_hash
54+
{:abc => 'def'}
55+
end
56+
end
57+
58+
@body = {"root" => SimpleExample.new}
59+
60+
subject.call({'PATH_INFO' => '/somewhere', 'HTTP_ACCEPT' => 'application/json'}).last.each{|b| b.should == '{"root":{"abc":"def"}}'}
61+
end
62+
5163
it 'should call #to_xml if the content type is xml' do
5264
@body = "string"
5365
@body.instance_eval do

0 commit comments

Comments
 (0)