There seems to be a limitation on how one can use the options hash with to_json. Take this example:
render :json => { :results => @posts.to_json(:only => [:title] ) }*
You don’t end up with what you want; instead of results being an array of posts, results becomes an escaped string. I recently put a patch on lighthouse that would cover this specific case
but after some further thought, I think a more general solution is in order.
Suppose to_json rather than returning a String instead returned a JSONString. We could then create an encoder for JSONString which does not re-escape itself when to_json is called on it.
You would then be free to do something like the example above and it would all “just work”. You’d also be able to pass different options to different AR collections being returned in the same result.
The problem is that to_json is really the wrong API for providing
custom JSON output.
We nearly always want to transform an object into *JSON-encodable
primitives*. Not into a JSON string.
So we split the brittle to_json API into as_json and to_json. Rather
than implement to_json to return a string, implement as_json to return
a JSON-encodable primitive. to_json converts the object using as_json
before encoding.
class Foo
# new way: return a JSON representation
def as_json
{ :foo => bar }
end
# old way: return a JSON string
def to_json(*ugly_internal_options)
{ :foo => bar }.to_json(*ugly_internal_options)
end
end