Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Version History

Version 1 Next »

We need a better convention for returning API results from collection endpoints.

Current behavior

Currently, when we return a collection of resources in an API, we use the default formatting provided by DRF, which returns a direct JSON list of results.  For example:

  [
{"id": 1, "item": "First item", "created": "2015-11-19T09:28:44Z"},
{"id": 2, "item": "Second item", "created": "2015-11-19T09:29:03Z"},
{"id": 3, "item": "Third item", "created": "2015-11-19T09:31:30Z"},
{"id": 4, "item": "Fourth item", "created": "2015-11-19T09:35:12Z"}
]

If we then paginate the results, using DRF's default pagination the above gets converted a JSON object that contains "previous" and "next" elements, which contain links to the previous and next pages respectively, a "count" element that contains the total number of results on all pages in the query, and a "results" element that contains the current page's results.  If the above example were paginated with three elements per page, the response would look like:

  {
"previous": null,
"next": "/path/to/results?page=2",
"count": 4,
"results": [
{"id": 1, "item": "First item", "created": "2015-11-19T09:28:44Z"},
{"id": 2, "item": "Second item", "created": "2015-11-19T09:29:03Z"},
{"id": 3, "item": "Third item", "created": "2015-11-19T09:31:30Z"}
]
}

Issues with current behavior

This is unsatisfactory for a few reasons:

  1. The results are in a different location depending on whether the query is paginated or not, which makes it more difficult to create a client to consume our data.
  2. The top level object controls pagination, which foregrounds meta-information while backgrounding the actual results the user was looking for. 
  3. It also doesn't play nicely with other metadata we might want to add, as we would either have to create new subsections for other kinds of metadata, which are then at a different level than the pagination, or dump it all into the top-level, which creates a mess of un-namespaced metadata.

Proposed behavior

I propose that we update our API conventions for collection endpoints to:

  1. Always return a JSON object, with an element "results", that contains a list of result items, whether or not the result set is paginated.

  2. If a result set is paginated, encapsulate pagination information under a top-level "pagination" entry alongside results.

This puts the results in a consistent location within the response, and provides a convenient namespace for the pagination metadata.  Any given result can be tested for pagination very easily: If the response object contains a "pagination" element, the results are paginated.

Examples

Unpaginated:

  {
"pagination": {
"count": 4,
"previous": null,
"next": "/path/to/results?page=2"
},
"results": [
{"id": 1, "item": "First item", "created": "2015-11-19T09:28:44Z"},
{"id": 2, "item": "Second item", "created": "2015-11-19T09:29:03Z"},
{"id": 3, "item": "Third item", "created": "2015-11-19T09:31:30Z"}
]
}

Paginated:

  {
"pagination": {
"count": 4,
"previous": null,
"next": "/path/to/results?page=2"
},
"results": [
{"id": 1, "item": "First item", "created": "2015-11-19T09:28:44Z"},
{"id": 2, "item": "Second item", "created": "2015-11-19T09:29:03Z"},
{"id": 3, "item": "Third item", "created": "2015-11-19T09:31:30Z"}
]
}

 

  • No labels