I have an existing Rails 3 application, to which I am adding a JSON API. We have a Vendor
ActiveRecord model, and an Employee
ActiveRecord model. An Employee
belongs to a Vendor
. In the API, we want to include an Employee
's Vendor
in the JSON serialization. For example:
# Employee as JSON, including Vendor
:employee => {
# ... employee attributes ...
:vendor => {
# ... vendor attributes ...
}
}
That's easy enough. However, I have a business requirement that the public API not expose the internal model names. That is, to the outside world, it needs to seem as though the Vendor
model is actually called Business
:
# Employee as JSON, including Vendor as Business
:employee => {
# ... employee attributes ...
:business => {
# ... vendor attributes ...
}
}
This is easy to do for the top-level object. That is, I could call @employee.as_json(:root => :dude_who_works_here)
to rename Employee
to DudeWhoWorksHere
in the JSON. But what about for included associations? I have tried a few things without success:
# :as in the association doesn't work
@employee.as_json(:include => {:vendor => {:as => :business}})
# :root in the association doesn't work
@employee.as_json(:include => {:vendor => {:root => :business}})
# Overriding Vendor's as_json doesn't work (at least, not in a association)
# ... (in vendor.rb)
def as_json(options)
super(options.merge({:root => :business}))
end
# ... elsewhere
@employee.as_json(:include => :vendor)
The only other idea I have is to manually rename the key, something like this:
# In employee.rb
def as_json(options)
json = super(options)
if json.key?(:vendor)
json[:business] = json[:vendor]
json.delete(:vendor)
end
return json
end
But that seems inelegant. I'm hoping there's a cleaner, more Rails-y way to do what I want. Any ideas?
Trying to generate complex JSON with the built-in options for as_json is clumsy. I would override as_json
in your models, and not bother with calling super
at all. Make up your own option keys for as_json
to control what you want to include in the Hash.
# employee.rb
def as_json(options = {})
json = {:name => name, ...} # whatever info you want to expose
json[:business] = vendor.as_json(options) if options[:include_vendor]
json
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With