Twitter is great for one-liners, but it's very difficult to carry on any kind of advanced conversation there. Therefore when I saw this tweet yesterday, I knew I'd be picking a different medium to reply:
— Maximilian 'Berghoff (@ElectricMaxxx) June 12, 2013
The blog seems like a good place, as I can put examples and all kinds other things here, and waffle at length (which is really why I like it!). Because when condensed to tweet form, the answer is really "it depends".
REST is all about representations of resources. They might come in different formats, and they might appear at their own URI as well as in one or more collections, but essentially you just get a representation of a thing. This is great, apart from when it isn't.
- What if you want a smaller result set with only a limited number of fields?
- What if you want related data? For every resource in a collection?
There are a couple of tactics that I deploy each time I need to solve one of these problems, but they all revolve around remodelling the resource structure. Just as we sometimes move fields around for database design or normalisation, we can do exactly the same with a RESTful service to make the resulting output make more sense to consumers. I thought I'd share examples of these tactics in this post.
More Verbose, Less Verbose
If a resource can be delivered in multiple formats, say XML or JSON, then why not in multiple "verbosities"? Sometimes you only want the outline of a resource, for example if you're display news items, you might only want the title and posting date. When you come to display that specific resource though, you'll want all the details, so you might end up with data structures like this:
- Full Article
- Collection of Related Articles
If you want an in-the-wild example, try the Joind.in API. All the records there come in a fairly minimal format, but you can request more fields by adding
verbose=yes as a GET parameter. Compare the API response (it's HTML, you can just click) for the recent DPC conference http://api.joind.in/v2.1/events/1109 with its verbose version http://api.joind.in/v2.1/events/1109?verbose=yes.
Splitting into Subresources
The alternative to allowing different verbosity of representations is to remove part of the record as it might be stored in the database into a separate resource.
So if your article is stored at http://example.com/articles/42, this would show the abbreviated version of the record from the structure above. Then you could offer the main body of the article at a separate location, such as http://example.com/articles/42/body. This does lead to repeated queries but if you only need the extra detail when you want to display a single record, it may well be worth the tradeoff - of course your mileage will vary between different applications.
Nesting Likely Data
The final tactic I want to share is where the server has a good idea that information will be needed from more than one source. There's a good example in the wild from GitHub - if you grab a list of issues over their API, you'll get the full user object of the user that created each issue. This makes sense because we'll always want to display who created the issue.
As an example, try requesting this URL with curl or your favourite API tool: https://api.github.com/repos/zendframework/zf2/issues and have a look at the structure that's returned (and as a total aside, admire the pretty-printing! I love GitHub's API)
There certainly are generic solutions, where you can basically express the select statement in URL form, but I'm not a huge fan of this approach. I'm sure there will be links to excellent resources in the comments of this article (thanks, people!)