sshefer
sshefer

Reputation: 239

Malformed Rails JSON and jQuery

I'm looking to return some data for a json request in rails and I was wondering if the data being returned is malformed. Here is a shortened example:

[{"company":{"name":"A"}},{"company":{"name":"B"}}]

I always thought that when returning json it should describe the root element and plurals, so it should return something more like:

{"companies":[{"name":"A"},{"name":"B"}]}

Here are the questions - Is there any way I can get my json to come out in that format? Is that even the correct format or does each company node need to be labeled as well? Do I have to create a custom view to get my results? What is the best way to get jQuery to loop the data in the current format? Right now I'm using:

format.json  { render :json => @companies.to_json() }

To render the results.

Thanks in advance for any help/advice.

Upvotes: 2

Views: 635

Answers (2)

Adam Lassek
Adam Lassek

Reputation: 35505

You're probably looking for something like the JSend specification. I came up with this myself before I realized it had been done before, because I've found it tremendously useful to have a standard response container for JSON services.

Here's how I would rewrite your server response:

format.json do
  render :json => {
    :status => 'success',
    :data => {
      :companies => @companies
    }
  }
end

There are times when you need to alter the attributes that are generated when converted to JSON. In these cases, I just use map:

format.json do
  render :json => {
    :status => 'success',
    :data => {
      :companies => @companies.map do |company|
        hash = company.attributes
        hash['address'] = company.address
        hash.delete('secret')
        hash
      end
    }
  }
end

A little more verbose than to_json, but it's more flexible and works just as well in Rack middleware.

Upvotes: 4

Matthew Flaschen
Matthew Flaschen

Reputation: 284816

Both are valid JSON. However, I would agree with you that the second is preferable. It's less redundant, since the first has an unnecessary object layer and repeats the company key. But a more subtle benefit is that the second protects you from JSON hijacking, which is only possible when the root structure is an array.

To loop the first, use e.g.

$.getJSON(url, functon(resp)
{
  for(var i = 0; i < resp.length; i++)
  {
     var company = resp[i].company;
     var name = company.name;
  }
});

Upvotes: 1

Related Questions