Upgrade to Pro — share decks privately, control downloads, hide ads and more …

An Introduction to the JSON:API Specification

Dan Gebhardt
October 16, 2019
580

An Introduction to the JSON:API Specification

Presented at the API Specifications Conference in Vancouver, BC.

Dan Gebhardt

October 16, 2019
Tweet

Transcript

  1. An introduction to
    Dan Gebhardt (@dgeb)
    Cerebris Corporation

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. "A Specification for Building APIs in JSON"

    View Slide

  6. "A Specification for Fetching and Mutating a Graph of Data"

    View Slide

  7. "A representation of resources and their relationships"
    Graph

    View Slide

  8. application/vnd.api+json

    View Slide

  9. Yehuda Katz
    @wycats
    Editors
    Dan Gebhardt
    @dgeb
    Gabe Sullice
    @gabesullice

    View Slide

  10. History
    • 2013 - Initial draft released by Yehuda Katz
    • 2015 - v1.0 released
    • 2018 - v1.1 draft released
    • 2019 - v1.1 progress continues ...

    View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. "The JSON:API Specification"
    or
    "jsonapi.org"

    View Slide

  17. View Slide

  18. View Slide

  19. " " " "

    View Slide

  20. application/vnd.api+json

    View Slide

  21. application/vnd.api+json

    View Slide

  22. application/vnd.[org]+json

    View Slide

  23. Sample of organizations that have either public APIs or public OSS projects that support JSON:API
    application/vnd.[org]+json

    View Slide

  24. Sample of organizations that have either public APIs or public OSS projects that support JSON:API
    application/vnd.api+json

    View Slide

  25. application/vnd.hal+json
    application/vnd.siren+json
    application/vnd.collection+json

    View Slide

  26. application/???+json

    View Slide

  27. View Slide

  28. Benefits

    View Slide

  29. Benefits
    • Shared conventions
    • Shared tooling
    • Standards-based best practices
    • Plays well with others
    • Gradual adoption

    View Slide

  30. Benefits
    • Shared conventions
    • Shared tooling
    • Standards-based best practices
    • Plays well with others
    • Gradual adoption

    View Slide

  31. Shared conventions

    View Slide

  32. Document structure
    +
    Processing rules
    Shared conventions

    View Slide

  33. Document structure

    View Slide

  34. {
    "data": {} | [{}] | null,
    "included": {},
    "links": {},
    "meta": {},
    "jsonapi": {},
    "errors": [{}]
    }
    Top-level structure

    View Slide

  35. {
    "data": {} | [{}] | null,
    "included": {},
    "links": {},
    "meta": {},
    "jsonapi": {},
    "errors": [{}]
    }
    Top-level structure
    }All optional
    Specific combinations disallowed

    View Slide

  36. {
    "data": {} | [{}] | null
    }
    Top-level structure

    View Slide

  37. {
    "data": {} | [{}] | null,
    "included": {},
    "links": {},
    "meta": {}
    }
    Top-level structure

    View Slide

  38. {
    "errors": [{}]
    }
    Top-level structure

    View Slide

  39. Primary data
    {
    "data": {} | [{}] | null
    }

    View Slide

  40. {
    "data": {
    "type": "article",
    "id": "123",
    "attributes": {
    "title": "Introduction to JSON:API",
    "published": "2019-10-11"
    }
    }
    }

    View Slide

  41. {
    "data": [{
    "type": "article",
    "id": "123",
    "attributes": {
    "title": "Introduction to JSON:API",
    "published": "2019-10-11"
    }
    }, {
    "type": "article",
    "id": "124",
    "attributes": {
    "title": "Retrospective on ASC 2019",
    "published": "2019-10-15"
    }
    }]
    }

    View Slide

  42. {
    "type": "article",
    "id": "123"
    }
    Resource object

    View Slide

  43. {
    "type": "article",
    "id": "123"
    }
    Resource object
    }Also called a
    "Resource Identity Object"
    in its simplest form

    View Slide

  44. {
    "type": "article",
    "id": "123",
    "attributes": {
    // ... this article's attributes
    },
    "relationships": {
    // ... this article's relationships
    },
    "links": {
    // ... links to this article
    },
    "meta": {
    // ... metadata about this article
    }
    }

    View Slide

  45. {
    "type": "article",
    "id": "123",
    "attributes": {
    "title": "Hello ASC 2019!"
    },
    "relationships": {
    "author": {
    "links": {
    "self": "/articles/123/relationships/author",
    "related": "/articles/123/author"
    }
    }
    }
    }

    View Slide

  46. {
    "links": {
    "self": "/articles/123/relationships/author",
    "related": "/articles/123/author"
    }
    }
    Relationship object

    View Slide

  47. {
    "links": {
    "self": "/articles/123/relationships/author",
    "related": "/articles/123/author"
    },
    "meta": {
    "created": "2019-10-15T18:13:25Z"
    }
    }
    Relationship object

    View Slide

  48. {
    "links": {
    "self": "/articles/123/relationships/author",
    "related": "/articles/123/author"
    },
    "meta": {
    "created": "2019-10-15T18:13:25Z"
    },
    "data": {
    "type": "person",
    "id": "123"
    }
    }
    Relationship object

    View Slide

  49. {
    "links": {
    "self": "/articles/123/relationships/author",
    "related": "/articles/123/author"
    },
    "meta": {
    "created": "2019-10-15T18:13:25Z"
    },
    "data": {
    "type": "person",
    "id": "123"
    }
    }
    Relationship object
    }Resource identity object(s), or
    "Linkage data"

    View Slide

  50. {
    "data": [{
    "type": "article", "id": "123",
    "relationships": {
    "author": {
    "data": { "type": "person", "id": "abc" }
    }
    }
    }],
    "included": [{
    "type": "person", "id": "abc",
    "attributes": {
    "name": "Dan Gebhardt"
    }
    }]
    }
    Compound Document

    View Slide

  51. {
    "data": [{
    "type": "article", "id": "123",
    "relationships": {
    "author": {
    "data": { "type": "person", "id": "abc" }
    }
    }
    }],
    "included": [{
    "type": "person", "id": "abc",
    "attributes": {
    "name": "Dan Gebhardt"
    }
    }]
    }
    Compound Document

    View Slide

  52. {
    "data": [
    {
    "type": "article",
    "id": "1",
    "attributes": {
    "title": "JSON:API paints my bikeshed!"
    },
    "relationships": {
    "author": {
    "data": { "type": "person", "id": "9" }
    },
    "comments": {
    "data": [
    { "type": "comments", "id": "5" }
    ]
    }
    }
    }
    ],
    // continued ...
    // ... continued
    "included": [
    {
    "type": "person",
    "id": "9",
    "attributes": {
    "name": "Dan Gebhardt"
    }
    },
    {
    "type": "comments",
    "id": "5",
    "attributes": {
    "body": "First!"
    },
    "relationships": {
    "author": {
    "data": { "type": "person", "id": "9" }
    }
    }
    }
    ]
    }

    View Slide

  53. {
    "data": [
    {
    "type": "article",
    "id": "1",
    "attributes": {
    "title": "JSON:API paints my bikeshed!"
    },
    "relationships": {
    "author": {
    "data": { "type": "person", "id": "9" }
    },
    "comments": {
    "data": [
    { "type": "comments", "id": "5" }
    ]
    }
    }
    }
    ],
    // continued ...
    // ... continued
    "included": [
    {
    "type": "person",
    "id": "9",
    "attributes": {
    "name": "Dan Gebhardt"
    }
    },
    {
    "type": "comments",
    "id": "5",
    "attributes": {
    "body": "First!"
    },
    "relationships": {
    "author": {
    "data": { "type": "person", "id": "9" }
    }
    }
    }
    ]
    }

    View Slide

  54. Links
    {
    "links": {
    "self": "/articles/123"
    }
    }

    View Slide

  55. Links
    {
    "links": {
    "self": "/articles/123",
    "doSomething": {
    "href": "/articles/123/doSomething",
    "meta": {
    "note": "POST to do something"
    }
    }
    }
    }

    View Slide

  56. Links
    {
    "links": {
    "self": "/articles/123",
    "doSomething": {
    "href": "/articles/123/doSomething",
    "meta": {
    "note": "POST to do something"
    }
    }
    }
    }
    }Allowed links locations:
    • Top-level
    • Resource objects
    • Relationship objects
    • Error objects

    View Slide

  57. {
    "meta": {
    "whatever": "you want",
    "can": {
    "go": "in meta"
    }
    }
    }
    Metadata

    View Slide

  58. {
    "meta": {
    "whatever": "you want",
    "can": {
    "go": "in meta"
    }
    }
    }
    Metadata
    }Allowed metadata locations:
    • Top-level
    • Resource objects
    • Resource identity objects
    • Link objects
    • Error objects

    View Slide

  59. Document structure
    +
    Processing rules
    Shared conventions

    View Slide

  60. Processing rules

    View Slide

  61. Opinionated HTTP usage

    View Slide

  62. Opinionated HTTP usage
    • GET
    • POST
    • PATCH
    • DELETE
    • Resources
    • Relationships

    View Slide

  63. • GET
    • POST
    • PATCH
    • DELETE
    • Resources
    • Relationships
    Opinionated HTTP usage

    View Slide

  64. • GET
    • POST
    • PATCH
    • DELETE
    • Resources
    • Relationships
    Opinionated HTTP usage

    View Slide

  65. Fetching
    GET /articles
    GET /articles/123
    Note: URL Structure is not dictated by JSON:API

    View Slide

  66. Graph Fetching
    GET /articles?include=author
    GET /articles?include=comments,author
    GET /articles?include=comments.author,author

    View Slide

  67. Sparse Fieldsets
    GET /articles?fields=title,author
    GET /articles?include=author&
    fields[article]=title,author&
    fields[person]=name

    View Slide

  68. Sorting
    GET /people?sort=age
    GET /people?sort=age,name
    GET /people?sort=-lastUpdated,name

    View Slide

  69. Pagination
    GET /people?page[???]=x
    }Pagination strategy agnostic:
    • Page-based
    • Cursor-based

    View Slide

  70. Filtering
    GET /people?filter[???]=x
    }Filtering strategy agnostic:
    • Simple, strict match
    • Nested conditions
    • Vertical-specific filtering

    View Slide

  71. • GET
    • POST
    • PATCH
    • DELETE
    • Resources
    • Relationships
    Opinionated HTTP usage
    Documented at jsonapi.org

    View Slide

  72. Benefits
    • Shared conventions
    • Shared tooling
    • Standards-based best practices
    • Plays well with others
    • Gradual adoption

    View Slide

  73. Shared tooling

    View Slide

  74. View Slide

  75. Server
    • Swift

    • PHP

    • Node.js

    • Ruby

    • Python

    • Go

    • .NET

    • Java
    • JavaScript

    • Typescript

    • iOS

    • Ruby

    • PHP

    • Dart

    • Perl
    Client
    Libraries
    • Scala

    • Elixir

    • Haskell

    • Perl

    • Vala

    • Rust

    • Dart
    • Java

    • Android

    • R

    • Elm

    • .NET

    • Python

    • Elixir
    74
    93

    View Slide

  76. Server
    netflix/fast_jsonapi

    google/jsonapi

    drupal/jsonapi

    cerebris/jsonapi-resources

    rails-api/active_model_serializers

    neomerx/json-api
    emberjs/data

    orbitjs/orbit

    crnk-project/crnk-framework

    jsonapi-ios/Spine

    reststate/Mobx

    reststate/Vuex
    Client
    Libraries

    View Slide

  77. Benefits
    • Shared conventions
    • Shared tooling
    • Standards-based best practices
    • Plays well with others
    • Gradual adoption

    View Slide

  78. Standards-based best practices

    View Slide

  79. Composition of standards
    • HTTP (RFC7231)
    • JSON (RFC8259)
    • URI (RFC3986)
    • Profiles (RFC6906)
    • Web linking (RFC8288)
    • UUID (RFC4122)
    • And more ...

    View Slide

  80. Composition of standards
    Evolution with those standards

    View Slide

  81. Composition of standards
    Benefit from ecosystems
    that support those standards

    View Slide

  82. Benefits
    • Shared conventions
    • Shared tooling
    • Standards-based best practices
    • Plays well with others
    • Gradual adoption

    View Slide

  83. Plays well with others
    • OpenAPI
    • JSON Schema
    • JSON-LD
    • And more ...

    View Slide

  84. Benefits
    • Shared conventions
    • Shared tooling
    • Standards-based best practices
    • Plays well with others
    • Gradual adoption

    View Slide

  85. You MAY use feature X.
    Gradual adoption
    If you detect feature X, you MUST do A, B, and C.

    View Slide

  86. Source: https://martinfowler.com/articles/richardsonMaturityModel.html
    Gradual adoption

    View Slide

  87. JSON:API v1.1

    View Slide

  88. JSON:API v1.1
    • Profiles
    • Extensions
    • Expanded hypermedia controls

    View Slide

  89. Profiles
    Extensions
    Specify meaning for members already reserved for users.
    Specify meaning for members reserved for the spec itself.

    View Slide

  90. Profiles
    Extensions
    Negotiated with the `profile` media type parameter.
    Negotiated with the `ext` media type parameter.

    View Slide

  91. Profiles
    Extensions
    May be ignored by servers.
    Must be supported or else error.

    View Slide

  92. POST /bulk HTTP/1.1
    Host: example.org
    Content-Type: application/vnd.api+json;ext="https://jsonapi.org/ext/atomic"
    Accept: application/vnd.api+json;ext="https://jsonapi.org/ext/atomic"
    {
    "atomic:operations": [{
    "op": "add",
    "href": "/blogPosts",
    "data": {
    "type": "articles",
    "attributes": {
    "title": "JSON API paints my bikeshed!"
    }
    }
    }]
    }
    Extension: Atomic Operations Experimental

    View Slide

  93. HTTP/1.1 200 OK
    Content-Type: application/vnd.api+json;ext="https://jsonapi.org/ext/atomic"
    {
    "atomic:results": [{
    "data": {
    "links": {
    "self": "http://example.com/blogPosts/13"
    },
    "type": "articles",
    "id": "13",
    "attributes": {
    "title": "JSON API paints my bikeshed!"
    }
    }
    }]
    }
    Extension: Atomic Operations Experimental

    View Slide

  94. {
    "atomic:operations": [{
    "op": "add",
    "data": {
    "type": "authors",
    "id": "acb2ebd6-ed30-4877-80ce-52a14d77d470",
    "attributes": {
    "name": "dgeb"
    }
    }
    },
    {
    "op": "add",
    "data": {
    "type": "articles",
    "id": "bb3ad581-806f-4237-b748-f2ea0261845c",
    "attributes": {
    "title": "JSON API paints my bikeshed!"
    },
    "relationships": {
    "author": {
    "data": {
    "type": "authors",
    "id": "acb2ebd6-ed30-4877-80ce-52a14d77d470"
    }
    }
    }
    }
    }]
    }
    }Multiple linked operations
    Experimental

    View Slide

  95. Expanded hypermedia controls

    View Slide

  96. View Slide

  97. Beyond JSON:API v1.1

    View Slide

  98. Beyond JSON:API v1.1
    • Optimize for HTTP/2/3
    • More extensions! More experiments!
    • Focus on DX via tooling
    (e.g. spectral rulesets)

    View Slide

  99. HTTP/1.1 Includes
    GET /articles?include=author
    GET /articles?include=comments,author
    GET /articles?include=comments.author,author

    View Slide

  100. HTTP/2 Server Push
    GET /articles?serverPush=author
    GET /articles?serverPush=comments,author
    GET /articles?serverPush=comments.author,author
    Experimental

    View Slide

  101. HTTP/2 Server Push Experimental

    View Slide

  102. Resources

    View Slide

  103. View Slide

  104. View Slide

  105. View Slide

  106. View Slide

  107. View Slide

  108. An introduction to
    Dan Gebhardt (@dgeb)
    Cerebris Corporation

    View Slide

  109. An introduction to
    Dan Gebhardt (@dgeb)
    Cerebris Corporation
    Thanks!
    jsonapi.org @jsonapi

    View Slide