I have a rest web service api, and I have a lot of stats that are aggregates of child data in an object. Where should I nest these stats? I thought about making them a resource all of their own, but it would mean a huge number of requests, instead of including them in a single json response.
For example:
GET /data
game:{
level: 1,
events:[
{event:...}
]
total_events: 23,
avg_events: 3
}
Or should things like total_events be within the events object?
I haven't found any good examples of how to this.
I'm not entirely sure I understand your intentions, but I would nevertheless put such aggregate information in the parent resource, along with the listing of child URLs.
If the child link list is too much trouble to build and the client is often only interested in the statistics, then you could introduce an extra query parameter to switch between the available respresentation formats. (e.g. "stats_only", "links", or "full".)
Related
A simple REST API:
GET: items/{id} - Returns a description of the item with the given id
PUT: items/{id} - Updates or Creates the item with the given id
DELETE: items/{id} - Deletes the item with the given id
Now the API-extension in question:
GET: items?filter - Returns all item ids matching the filter
PUT: items - Updates or creates a set of items as described by the JSON payload
[[DELETE: items - deletes a list of items described by JSON payload]] <- Not Correct
I am now being interested in the DELETE and PUT operation recycling functionality that can be easily accessed by PUT/DELETE items/{id}.
Question: Is it common to provide an API like this?
Alternative: In the age of Single Connection Multiple Requests issuing multiple requests is cheap and would work more atomic since a change either succeeds or fails but in the age of NOSQL database a change in the list might already have happend even if the request processing dies with internal server or whatever due to whatever reason.
[UPDATE]
After considering White House Web Standards and Wikipedia: REST Examples the following Example API is now purposed:
A simple REST API:
GET: items/{id} - Returns a description of the item with the given id
PUT: items/{id} - Updates or Creates the item with the given id
DELETE: items/{id} - Deletes the item with the given id
Top-resource API:
GET: items?filter - Returns all item ids matching the filter
POST: items - Updates or creates a set of items as described by the JSON payload
PUT and DELETE on /items is not supported and forbidden.
Using POST seems to do the trick as being the one to create new items in an enclosing resource while not replacing but appending.
HTTP Semantics POST Reads:
Extending a database through an append operation
Where the PUT methods would require to replace the complete collection in order to return an equivalent representation as quoted by HTTP Semantics PUT:
A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being returned in a 200 (OK) response.
[UPDATE2]
An alternative that seems even more consistent for the update aspect of multiple objects seems to be the PATCH method. The difference between PUT and PATCH is described in the Draft RFC 5789 as being:
The difference between the PUT and PATCH requests is reflected in the way the server processes the enclosed entity to modify the resource identified by the Request-URI. In a PUT request, the enclosed entity is considered to be a modified version of the resource stored on the origin server, and the client is requesting that the stored version be replaced. With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version. The PATCH method affects the resource identified by the Request-URI, and it also MAY have side effects on other resources; i.e., new resources may be created, or existing ones modified, by the application of a PATCH.
So compared to POST, PATCH may be also a better idea since PATCH allows an UPDATE where as POST only allows appending something meaning adding without the chance of modification.
So POST seems to be wrong here and we need to change our proposed API to:
A simple REST API:
GET: items/{id} - Returns a description of the item with the given id
PUT: items/{id} - Updates or Creates the item with the given id
DELETE: items/{id} - Deletes the item with the given id
Top-resource API:
GET: items?filter - Returns all item ids matching the filter
POST: items - Creates one or more items as described by the JSON payload
PATCH: items - Creates or Updates one or more items as described by the JSON payload
You could PATCH the collection, e.g.
PATCH /items
[ { id: 1, name: 'foo' }, { id: 2, name: 'bar' } ]
Technically PATCH would identify the record in the URL (ie PATCH /items/1 and not in the request body, but this seems like a good pragmatic solution.
To support deleting, creating, and updating in a single call, that's not really supported by standard REST conventions. One possibility is a special "batch" service that lets you assemble calls together:
POST /batch
[
{ method: 'POST', path: '/items', body: { title: 'foo' } },
{ method: 'DELETE', path: '/items/bar' }
]
which returns a response with status codes for each embedded requests:
[ 200, 403 ]
Not really standard, but I've done it and it works.
Updating Multiple Resources With One Request - Is it standard or to be avoided?
Well, sometimes you simply need to perform atomic batch operations or other resource-related operations that just do not fit the typical scheme of a simple REST API, but if you need it, you cannot avoid it.
Is it standard?
There is no universally accepted REST API standard so this question is hard to answer. But by looking at some commonly quoted api design guidelines, such as jsonapi.org, restfulapi.net, microsoft api design guide or IBM's REST API Conventions, which all do not mention batch operations, you can infer that such operations are not commonly understood as being a standard feature of REST APIs.
That said, an exception is the google api design guide which mentions the creation of "custom" methods that can be associated via a resource by using a colon, e.g. https://service.name/v1/some/resource/name:customVerb, it also explicitly mentions batch operations as use case:
A custom method can be associated with a resource, a collection, or a service. It may take an arbitrary request and return an arbitrary response, and also supports streaming request and response. [...] Custom methods should use HTTP POST verb since it has the most flexible semantics [...] For performance critical methods, it may be useful to provide custom batch methods to reduce per-request overhead.
So in the example case you provided you do the following according to google's api guide:
POST /api/items:batchUpdate
Also, some public APIs decided to offer a central /batch endpoint, e.g. google's gmail API.
Moreover, as mentioned at restfulapi.net, there is also the concept of a resource "store", in which you store and retrieve whole lists of items at once via PUT – however, this concept does not count for server-managed resource collections:
A store is a client-managed resource repository. A store resource lets an API client put resources in, get them back out, and decide when to delete them. A store never generates new URIs. Instead, each stored resource has a URI that was chosen by a client when it was initially put into the store.
Having answered your original questions, here is another approach to your problem that has not been mentioned yet. Please note that this approach is a bit unconventional and does not look as pretty as the typical REST API endpoint naming scheme. I am personally not following this approach but I still felt it should be given a thought :)
The idea is that you could make a distinction between CRUD operations on a resource and other resource-related operations (e.g. batch operations) via your endpoint path naming scheme.
For example consider a RESTful API that allows you to perform CRUD operations on a "company"-resource and you also want to perform some "company"-related operations that do not fit in the resource-oriented CRUD-scheme typically associated with restful api's – such as the batch operations you mentioned.
Now instead of exposing your resources directly below /api/companies (e.g. /api/companies/22) you could distinguish between:
/api/companies/items – i.e. a collection of company resources
/api/companies/ops – i.e. operations related to company resources
For items the usual RESTful api http-methods and resource-url naming-schemes apply (e.g. as discussed here or here)
POST /api/companies/items
GET /api/companies/items
GET /api/companies/items/{id}
DELETE /api/companies/items/{id}
PUT /api/companies/items/{id}
Now for company-related operations you could use the /api/companies/ops/ route-prefix and call operations via POST.
POST /api/companies/ops/batch-update
POST /api/companies/ops/batch-delete
POST /api/companies/ops/garbage-collect-old-companies
POST /api/companies/ops/increase-some-timestamps-just-for-fun
POST /api/companies/ops/perform-some-other-action-on-companies-collection
Since POST requests do not have to result in the creation of a resource, POST is the right method to use here:
The action performed by the POST method might not result in a resource that can be identified by a URI.
https://www.rfc-editor.org/rfc/rfc2616#section-9.5
As far as I understand the REST concept it covers an update of multiple resources with one request. Actually the trick here is to assume a container around those multiple resources and take it as one single resource. E.g. you could just assume that list of IDs identifies a resource that contains several other resources.
In those examples in Wikipedia they also talk about resources in Plural.
I'm working on a RESTful HTTP API for an embedded hardware device. In this API, hardware components are typically represented in a URI hierarchy of API Resources, which then have child JSON objects with attributes/fields specific to that hardware "object". To control/modify the hardware, a HTTP PUT request is sent with a content-body of JSON object containing desired fields to be changed.
My question is about the order of fields within a JSON request body. Let's say we are changing multiple fields in the same JSON object. Since a JSON object is, by definition, an "unordered collection of zero or more name/value pairs", this implies that the order of applying those hardware changes is also unordered/undefined, which might not be good.
For example, what if "setting1" must be configured before "state" is set? For example, the following might be sent as the content-body:
{
"setting1": 1234,
"state": "on",
}
But if we send the following instead, what happens? (Notice the "state" field occurs first.)
{
"state": "on",
"setting1": 1234,
}
The problem is, by default the context of the JSON Object is "unordered", so the behavior is uncertain.
If it could be established (perhaps through API documentation) that the order of JSON fields in a request is significant, would this be considered a violation of best-practices in the context of JSON and RESTful APIs? How have others dealt with this? I would be surprised if this has not been discussed already, but I have not been able to find anything.
I'm not certain, but I think that trying to impose an ordering restriction on clients is going to be problematic for some of them. I would bet that not all frameworks/JSON libraries will respect an ordering, at least not by default. If you control the client, this may not be a big deal, but it sounds like you don't.
Strictly speaking, you would have to send multiple PUT requests in order to ensure the updates happen in the correct order. That's the easiest to implement, but also the noisiest. Another option would be to instead support a PATCH call to the endpoint using the RFC 6902 format. That will let you control the order in which changes occur, but your clients need to build out PATCHes. You could also support a POST if neither of those appeal to you.
I have java library that runs webservices and these return a response in XML. The webservices all revolve around giving a list of details about items. Recently, changes were made to allow the services to return JSON by simply converting the XML to JSON. When looking at the responses, I saw they're not as easy to parse as I thought. For example, a webservice that returns details about items.
If there are no items, the returned JSON is as follows:
{"ItemResponse":""}
If there is 1 item, the response is as follows (now itemResponse has a object as value instead of a string):
{"ItemResponse":{"Items":{"Name":"Item1","Cost":"$5"}}}
If there two or more items, the response is (now items has an array as value instead of an object):
{"ItemResponse":{"Items":[{"Name":"Item1","Cost":"$5"},{"Name":"Item2","Cost":"$3"}]}}
To parse these you need several if/else which I think are clunky.
Would it be an improvement if the responses were:
0 items: []
1 item: [{"Name":"Item1","Cost":"$5"}]
2 items: [{"Name":"Item1","Cost":"$5"},{"Name":"Item2","Cost":"$3"}]
This way there is always an array, and it contains the itemdata. An extra wrapper object is possible:
0 items: {"Items":[]}
1 item: {"Items":[{"Name":"Item1","Cost":"$5"}]}
2 items: {"Items":[{"Name":"Item1","Cost":"$5"},{"Name":"Item2","Cost":"$3"}]}
I'm not experienced in JSON so my question is, if you were a developer having to use these webservices, how would you expect the JSON resonse to be formatted? Is it better to always return a consistent array, even if there are no items or is this usually not important? Or is an array not enough and do you really expect a wrapper object around the array?
What are conventions/standards regarding this?
Don't switch result types, always return an array if there are more items possible. Do not mix, for 1 item an object for more an array. That's not a good idea.
Another best practise is that you should version your API. Use something like yoursite.com/api/v1/endpoint. If you don't do this and you change the response of your API. All your client apps will break. So keep this in mind together with documentation. (I've seen this happen a lot in the past..)
As a developer I personally like your second approach, but again it's a preference. There is no standard for this.
There are several reasons to use json:
much more dense and compact: thus data sent is less
in javascript you can directly access those properties without parsing anything. this means you could convert it into an object read the attributes (often used for AJAX)
also in java you usually don't need to parse the json by yourself - there are several nice libs like www.json.org/java/index.html
if you need to know how json is build ... use google ... there tons of infos.
To your actual questions:
for webservices you often could choose between xml and json as a "consumer" try:
https://maps.googleapis.com/maps/api/place/textsearch/json
and
https://maps.googleapis.com/maps/api/place/textsearch/xml
there is no need to format json visually - is it not meant for reading like xml
if your response doesn't have a result, json-service often still is giving a response text - look again at the upper google map links - those are including a response status which makes sense as it is a service.
Nevertheless it's the question if it is worth converting from xml to json if there isn't a specific requirement. As Dieter mentioned: it depends on who is already using this service and how they are consumed ... which means the surrounding environment is very important.
So I have a theoretical question based on a lot of research that I have done recently with regards to REST API interfaces.
Firstly I understand that in REST, resources should be nouns and not verbs and each resource should be decoupled from the next resource, however the resources can return the same entities or collection of entities, depending on the purpose of the resource.
My focus however is performing restful search.
In all the research I have done, the most common solution I have come across is the use of parameters in the URL
api.test.com/search-cars?param1=val1¶m2=val2
Now while this is standard practice and is not truly breaking the rules of REST, why is it that no one represents the search parameters as an id (possibly in the form of JSON)
api.test.com/cars/{"color":"blue","year":"2013","make":"toyota"}
If I look at cars as a resource and represent my id as a JSON, I could easily say that I truly have a finite number of cars thus a finite and unique number of id's.
Further more this promotes pure rest by conforming to "resource/id"
What are the benefits and downsides to using parameters as in the first example?
What are the benefits and downsides to using JSON as an id with the "filters" as in the second example?
All your comments would be really helpful as I need to take a final decision on how to move forward with the first resource of my API. Also, I need to have a strong argument for my boss explaining why I decided on either of the methods.
The general form of an URL is
scheme://domain:port/path?query_string#fragment_id
So you propose two URLs:
search by query_string
search by last path segment
Search by query_string
I recommend to name the collection cars, not search-cars. As you write in your question, URLs identify resources. The cars resource identifies the collection of all cars. I have no idea what collection a resource called search-cars would identify.
GET http://api.test.com/cars
would return the collection of all cars.
GET http://api.test.com/cars/123
would return the car identified by 123.
GET http://api.test.com/cars?color=blue&year=2013
would return the collection of all blue cars build in 2013.
Search by path
Your second URL
GET http://api.test.com/cars/{"color":"blue","year":"2013","make":"toyota"}
would make the query (JSON) a part of the path. To make the two examples equal, I suppose to make the JSON a query parameter:
GET http://api.test.com/cars?search={"color":"blue","year":"2013","make":"toyota"}
JSON vs. named query parameters
Most REST frameworks support mapping of query params to method parameters.
Most REST frameworks allow you to map a path segment to a method parameter. And, again, most REST frameworks allow you to map JSON to an object or a simple dictionary.
What makes JSON harder to use is the need to escape the "{} characters:
{"color":"blue","year":"2013","make":"toyota"}
becomes
%7B%22color%22%3A%22blue%22%2C%22year%22%3A%222013%22%2C%22make%22%3A%22toyota%22%7D
which is not very nice.
Summary
You can use both the query_string and the path of the URL to identify a resource. Search parameters are better placed in the query_string because the ? can mentally be translated to the WHERE of SQL.
Don't use JSON in URLs because escaped JSON is hard to read.
I am building an API that uses JSON for requests/responses. I want to be able to also receive bulk requests, i.e., JSON Arrays.
Right now, I have a solution which works fine if the JSON request is always wrapped in an array:
[
{"id":"AAAEEF", "value":"abc"}
]
works, also
[
{"id":"AAAEEF", "value":"abc"},
{"id":"AAAEF1", "value":"vbc"},
]
If one wants to request only a single id-value combination and thus requests
{"id":"AAAEEF", "value":"abc"}
the request fails.
My question: Is it acceptable for a "good" API to enforce wrapping all JSON requests in an array, even if they only have one element?
Thanks in advance for helping me out!
The key to writing a "good" API is to be consistent, and to document it well. Whatever choices you make next are yours to make - if you decide you have good reason to require all calls to your API should be wrapped in a thisIsAContainerObject element, by all means document it and release it.
For consistency it might even be explicitly better to always require an array. As long as you throw a proper error when more than one element is inserted.