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

An Introduction to the JSON:API Specification

Dan Gebhardt
October 16, 2019
630

An Introduction to the JSON:API Specification

Presented at the API Specifications Conference in Vancouver, BC.

Dan Gebhardt

October 16, 2019
Tweet

Transcript

  1. History • 2013 - Initial draft released by Yehuda Katz

    • 2015 - v1.0 released • 2018 - v1.1 draft released • 2019 - v1.1 progress continues ...
  2. Sample of organizations that have either public APIs or public

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

    OSS projects that support JSON:API application/vnd.api+json
  4. Benefits • Shared conventions • Shared tooling • Standards-based best

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

    practices • Plays well with others • Gradual adoption
  6. { "data": {} | [{}] | null, "included": {}, "links":

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

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

    {}, "meta": {} } Top-level structure
  9. { "data": { "type": "article", "id": "123", "attributes": { "title":

    "Introduction to JSON:API", "published": "2019-10-11" } } }
  10. { "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" } }] }
  11. { "type": "article", "id": "123" } Resource object }Also called

    a "Resource Identity Object" in its simplest form
  12. { "type": "article", "id": "123", "attributes": { // ... this

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

    2019!" }, "relationships": { "author": { "links": { "self": "/articles/123/relationships/author", "related": "/articles/123/author" } } } }
  14. { "links": { "self": "/articles/123/relationships/author", "related": "/articles/123/author" }, "meta": {

    "created": "2019-10-15T18:13:25Z" }, "data": { "type": "person", "id": "123" } } Relationship object
  15. { "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"
  16. { "data": [{ "type": "article", "id": "123", "relationships": { "author":

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

    { "data": { "type": "person", "id": "abc" } } } }], "included": [{ "type": "person", "id": "abc", "attributes": { "name": "Dan Gebhardt" } }] } Compound Document
  18. { "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" } } } } ] }
  19. { "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" } } } } ] }
  20. 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
  21. { "meta": { "whatever": "you want", "can": { "go": "in

    meta" } } } Metadata }Allowed metadata locations: • Top-level • Resource objects • Resource identity objects • Link objects • Error objects
  22. Opinionated HTTP usage • GET • POST • PATCH •

    DELETE • Resources • Relationships
  23. • GET • POST • PATCH • DELETE • Resources

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

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

    • Relationships Opinionated HTTP usage Documented at jsonapi.org
  26. Benefits • Shared conventions • Shared tooling • Standards-based best

    practices • Plays well with others • Gradual adoption
  27. 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
  28. Benefits • Shared conventions • Shared tooling • Standards-based best

    practices • Plays well with others • Gradual adoption
  29. Composition of standards • HTTP (RFC7231) • JSON (RFC8259) •

    URI (RFC3986) • Profiles (RFC6906) • Web linking (RFC8288) • UUID (RFC4122) • And more ...
  30. Benefits • Shared conventions • Shared tooling • Standards-based best

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

    practices • Plays well with others • Gradual adoption
  32. You MAY use feature X. Gradual adoption If you detect

    feature X, you MUST do A, B, and C.
  33. Profiles Extensions Specify meaning for members already reserved for users.

    Specify meaning for members reserved for the spec itself.
  34. 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
  35. 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
  36. { "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
  37. Beyond JSON:API v1.1 • Optimize for HTTP/2/3 • More extensions!

    More experiments! • Focus on DX via tooling (e.g. spectral rulesets)