Your anti bikeshedding weapon.
By following shared conventions, you can increase productivity, take advantage of generalized tooling, and focus on what matters: your application.
{
"links": {
"self": "http://example.com/articles",
"next": "http://example.com/articles?page[offset]=2",
"last": "http://example.com/articles?page[offset]=10"
},
"data": [{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON API paints my bikeshed!"
},
"relationships": {
"author": {
"links": {
"self": "http://example.com/articles/1/relationships/author",
"related": "http://example.com/articles/1/author"
},
"data": { "type": "people", "id": "9" }
},
"comments": {
"links": {
"self": "http://example.com/articles/1/relationships/comments",
"related": "http://example.com/articles/1/comments"
},
"data": [
{ "type": "comments", "id": "5" },
{ "type": "comments", "id": "12" }
]
}
},
"links": {
"self": "http://example.com/articles/1"
}
}],
"included": [{
"type": "people",
"id": "9",
"attributes": {
"first-name": "Dan",
"last-name": "Gebhardt",
"twitter": "dgeb"
},
"links": {
"self": "http://example.com/people/9"
}
}, {
"type": "comments",
"id": "5",
"attributes": {
"body": "First!"
},
"relationships": {
"author": {
"data": { "type": "people", "id": "2" }
}
},
"links": {
"self": "http://example.com/comments/5"
}
}, {
"type": "comments",
"id": "12",
"attributes": {
"body": "I like XML better"
},
"relationships": {
"author": {
"data": { "type": "people", "id": "9" }
}
},
"links": {
"self": "http://example.com/comments/12"
}
}]
}
- Relationships
- Links
- Sideloading
- Conventions, continued
Hypermedia As The Engine Of Application State (HATEOAS) is a component of the REST application architecture that distinguishes it from other network application architectures.
With HATEOAS, a client interacts with a network application whose application servers provide information dynamically through hypermedia. A REST client needs little to no prior knowledge about how to interact with an application or server beyond a generic understanding of hypermedia. – https://en.wikipedia.org/wiki/HATEOAS
{
data: {
id: '100'
name: 'Ada',
tenant_id: '2', // "has one tenant"
planning_unit_ids: ['1', '2'], // "has many planning_units"
}
}
JSON:API links objects
GET /users/100?include=tenant,planning_units
GET /articles/1?include=comments,comments.author
{
data: {
id: '100'
type: 'users',
attributes: {
name: 'Ada'
},
relationships: {
// "has one tenant"
tenant: {
links: {
related: https://example.com/tenants/2
}
},
// "has many planning_units"
planning_units: {
links: {
related: https://example.com/users/planning_units/1,2
}
}
}
}
JSON:API resource linkage.
{
data: {
id: '100',
type: 'users',
relationships: {
// "has one tenant"
tenant: {
links: {
related: 'https://example.com/tenants/2'
}
data: {
type: 'tenant',
id: '2'
}
},
// "has many planning_units"
planning_units: {
links: {
related: 'https://example.com/users/planning_units/1,2'
}
data: [
{
type: 'planning_unit',
id: '1'
},
{
type: 'planning_unit',
id: '2'
}
]
}
}
}
}
PATCH /articles/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "articles",
"id": "1",
"relationships": {
"author": {
"data": { "type": "people", "id": "1" }
}
}
}
}
PATCH /articles/1/relationships/author HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": { "type": "people", "id": "12" }
}
{
"data": {
"type": "invoice",
"id": "093b941d",
"links": {
"pay": "https://example.com/invoices/093b941d/payment_attempts"
}
"attributes": {
"created_at": "2017-06-15 12:31:01Z",
"sent_at": "2017-06-15 12:34:29Z",
"paid_at": "2017-06-16 09:05:00Z",
"status": "published"
}
},
}
Inclusion of Related Resources
GET /articles/1?include=author
{
data: {
id: '1',
type: 'article',
attributes: {
title: 'An Article'
},
relationships: {
author: {
data: {
type: 'author',
id: '2'
}
}
}
},
included: [
{
id: '1',
type: 'author',
attributes: {
name: 'Bob'
},
}
]
}
Filtering
GET https://example.com/articles?filter[author]=1
Sparse fieldsets
GET https://example.com/articles?fields[articles]=title,created_at,author
Pagination