Introduction
This proposal is a work in progress and aims to address the perceived problems with various REST and JSON style guides with the goal of providing the following:
- Ease of data access. The client should never need to iterate through lists of objects on single resource requests. Data should be available as properties.
- Metadata specific to the request but separate from the resource data.
- Bundling of data in the response. Multiple resources and resource lists SHOULD be supported.
- Name-safe. Naming conflicts and reserved properties MUST be avoided.
- Normalized responses. Single objects MUST have the same structure as lists of resources, so client code can accept resources regardless of their origin. However, single resource requests MAY be more detailed.
- Type independent. Clients MUST NOT need to check the type of a property. The use of
data
anddataList
reflects the decision to use different properties for different types. - Responses and requests formats MUST match. Requests and responses MUST use the
data: {resource:}
ordataList: {resource:}
formats.
Terminology
The terms object, member, array, number, name, and string in this document are to be interpreted as described in RFC 7159.
The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC 2119.
Data Format
Server request and response bodies, if present, should contain JSON.
Auto-discovery
A server MUST implement a options
call. The request method SHOULD allow this request as GET or OPTIONS. The uri SHOULD be /options
.
{ "status": 200, "options": { "myResource": { "href": "/my-resource", "controllers": { "update": { "uri": "/update", "method": "POST", }, "list": { "uri": "/list", "method": "GET", "multi": true } } } } }
Using the above example, a client should be able to build request urls fairly easily.
For example, to call the controller update
on myResource
with ID of 7
, one would call: /my-resource/7/update
.
To call the list
multi controller on myResource
one would call: /my-resource/list
.
Requests
Resource POST/PUT
A post to a single resource MUST use the data
property.
{ "data": { "myResource": { "myField": "Some value", "myOtherField": "Foo" } } }
Resource list POST/PUT
POSTing to multiples of the same resource (such as a bulk create operation) MUST use the dataList
property.
{ "dataList": { "myResource": [ {"myField": "Some value", "myOtherField": "Some other value" }, {"myField": "Foo", "myOtherField": "bar" } ] } }
A server MAY support multiple dataList
objects.
{ "dataList": { "author": [ {"name":"Bill", "id":1}, {"name":"Sally", "id":2} ], "articles": [ {"title":"Bill's Article", "authorId":1}, {"title":"Sally's Article", "aithorId":2} ] } }
Responses
Resource response
More than one resource MAY be returned, but only one of each type of resource.
Resource responses SHOULD contain meta
and data
objects.
Meta data can be updated in the client's scope on each request.
This is the reason an options
request does NOT use meta
, since options
should
only need to be retrieved once.
{ "status": 200, "error": "A server-level error, such as a caught but unknown exception", "data": { "myResource": { "myField": "foo", "myOtherField": "bar" } }, "meta": { "myResource": { "errors": ["List of Object-level errors"], "fields": { "myField": { "error": "Field-specific error" } } }, } }
Members
meta
- OPTIONAL. A meta object describes request messaging.data
- REQUIRED. This is the data returned from a single resource GET request. However,data
is OPTIONAL for POST, PUT, and DELTE requests.
Access examples
- Field value:
data.myResource.myField
- Field metadata:
meta.myResource.fields.myField
Resource list response
The server MUST return lists of data using the dataList
property instead of data
. This is because a client
MUST NOT be required to type-check.
{ "status": 200, "error": "A server-level error, such as a caught but unknown exception", "dataList": { "myResource": [ { "myField": "foo", "myOtherField": "bar" }, { "myField": "baz", "myOtherField": "quux" } ] }, "meta": { "myResource": { "errors": ["List of Object-level errors"], "fields": { "myField": { "error": "Field-specific error" } } } } }
Members
meta
- OPTIONAL Same format as single resource requests.dataList
- REQUIRED. Contains one or more properties with the name of a resource, and the value of each property is a list of resource objects.
Access examples
- Field value:
dataList.myResource[1].myField
- Field metadata:
meta.myResource.fields.myField
(The same as with other requests)