Skip to content

Conforming to jsonapi.org format

Dan Matthews edited this page Feb 17, 2014 · 12 revisions

Conforming to JSON API format

There is a new attempt to standardize the JSON format of APIs in order to establish predictability and consistency at jsonapi.org. This is a guide to adhering to the jsonapi.org conventions using RABL templating.

For the time being, this guide assumes "ID-Based JSON API" rather than Link based but either approach should be pretty straightforward.

Setup

In order to conform to the specification, we may want to disable the child root and enable the 'json' root as defaults for RABL:

Rabl.configure do |config|
  config.include_json_root = true
  config.include_child_root = false
end

Singular Resources

Singular resources are represented as JSON objects. However, they are still wrapped inside an array:

{
  "posts": [{
    "id" : 56,
    "title" : "Foo"
  }]
}

This simplifies processing, as you can know that a resource key will always be a list.

In RABL, this is easy to achieve:

# app/views/posts/show.rabl
collection [@post] => :posts
attributes :id, :title

This will return the expected format for singular resources, still returned as a list according to the guide in order to "simplify processing, as you can know that a resource key will always be a list".

Resource Collections

If the length of an array at a resource key is greater than one, the value represents a list of documents.

{
  "posts": [{
    "id" : 56,
    "title" : "Foo"
  }, {
    "id" : 57,
    "title" : "Bar"
  }]
}

Each document in the list MUST contain an id key.

In RABL, this is easy to achieve:

# app/views/posts/index.rabl
collection @posts => :posts
attributes :id, :title

This will return the expected format for resource collections.

Relationships

The value of the "links" key is a JSON object that represents related documents.

{
  "posts": [{
    "id": "1",
    "title": "Rails is Omakase",
    "links": {
      "author": "9",
      "comments": [ "5", "12", "17", "20" ]
    }
  }]
}

In the above example, a GET request to /posts/1/comments returns a document containing the four specified comments.

In the above example, a GET request to /people/9 returns a document containing the specified author.

In the above example, a GET request to /comments?ids=5,12,17,20 returns a document containing the four specified comments.

In RABL, assuming the model relationships are setup, this can be done with the following:

# app/views/posts/show.rabl
collection [@post] => :posts
attributes :id, :title
node :links do |post|
  {
    author: post.author_id,
    comments: post.comment_ids
  }
end

It is the responsibility of your controller or route actions to support the ability to GET various resources based on the associated ids.