Getting to JSON:API: What it is, why you should use it, and how to use it in Laravel

60187fe0ab07ea5a46572a3ab05f61dd?s=47 Matt Stauffer
February 26, 2020

Getting to JSON:API: What it is, why you should use it, and how to use it in Laravel

Getting to JSON:API: What it is, why you should use it, and how to use it in Laravel

60187fe0ab07ea5a46572a3ab05f61dd?s=128

Matt Stauffer

February 26, 2020
Tweet

Transcript

  1. HOW TO JSON:API QUICKLY & EASILY IN LARAVEL Getting to

    JSON:API - Matt Stauffer
  2. You can't. THE END Getting to JSON:API - Matt Stauffer

  3. GETTING TO JSON:API WHAT IT IS, WHY YOU SHOULD USE

    IT, and HOW TO USE IT IN LARAVEL Getting to JSON:API - Matt Stauffer
  4. First half: Theory ▸ 1. Intro to REST APIs ▸

    2. The State of APIs ▸ 3. What is JSON:API? ▸ 4. Why JSON:API? Getting to JSON:API - Matt Stauffer
  5. Second half: Implementation ▸ 5. JSON:API Tooling in Laravel ▸

    6. Other API concerns ▸ 7. After the talk ▸ 8. Outro Getting to JSON:API - Matt Stauffer
  6. PART 1 Intro to REST APIS Getting to JSON:API -

    Matt Stauffer
  7. REST: CRUD over JSON using HTTP verbs Getting to JSON:API

    - Matt Stauffer
  8. REST: CRUD over JSON using HTTP verbs shaped like /dogs/14

    and stuff Getting to JSON:API - Matt Stauffer
  9. What's "REST", anyway? Getting to JSON:API - Matt Stauffer

  10. REPRESENTATIONAL STATE TRANSFER Getting to JSON:API - Matt Stauffer

  11. ROY FIELDING Getting to JSON:API - Matt Stauffer

  12. REST is: ▸ Client/server ▸ Stateless ▸ Cacheable ▸ Layered

    (proxyable, load balanceable) ▸ Uniform Interface: ▸ Resource identification in requests ▸ Resource manipulation through representations ▸ Self-descriptive messages (content headers) ▸ Hypermedia as the Engine of Application State Getting to JSON:API - Matt Stauffer
  13. REST misconceptions: ▸ REST has no preferred URL patterns ▸

    REST needn't be JSON ▸ Most REST-ish APIs aren't actually RESTful, but that's fine Getting to JSON:API - Matt Stauffer
  14. What's "HATEOAS"? Getting to JSON:API - Matt Stauffer

  15. What's "HATEOAS"? Getting to JSON:API - Matt Stauffer

  16. What's "HATEOAS"? HYPERMEDIA AS THE ENGINE OF APPLICATION STATE Getting

    to JSON:API - Matt Stauffer
  17. What's "HYPERMEDIA"? Getting to JSON:API - Matt Stauffer

  18. AN EXAMPLE OF EMBEDDED HYPERMEDIA /* GET /departments/10 */ {

    "type": "departments", "id": "10", "attributes": { "name": "Information Technology" } } Getting to JSON:API - Matt Stauffer
  19. AN EXAMPLE OF EMBEDDED HYPERMEDIA /* GET /departments/10 */ {

    "type": "departments", "id": "10", "attributes": { "name": "Information Technology" }, "links": [ { "href": "departments/10/employees", "rel": "employees", "type" : "GET" } ] } Getting to JSON:API - Matt Stauffer
  20. APIS AS STATE MACHINES Getting to JSON:API - Matt Stauffer

  21. SHOULD WE AIM FOR TRUE HATEOAS? Getting to JSON:API -

    Matt Stauffer
  22. "Hard coding URIs in your documentation and thus also in

    all of the clients of your API, is a clear violation of the REST constraint that hypermedia must be the engine of application state." - Asbjørn Ulsberg Getting to JSON:API - Matt Stauffer
  23. SHOULD WE AIM FOR TRUE HATEOAS? PROBABLY NOT. Getting to

    JSON:API - Matt Stauffer
  24. Getting to JSON:API - Matt Stauffer

  25. Getting to JSON:API - Matt Stauffer

  26. GRADUAL ADOPTION. Getting to JSON:API - Matt Stauffer

  27. PART 2 THE STATE OF APIS Getting to JSON:API -

    Matt Stauffer
  28. WE'RE IN THE BAD OLD DAYS WHEN IT COMES TO

    API STANDARDIZATION Getting to JSON:API - Matt Stauffer
  29. Getting to JSON:API - Matt Stauffer

  30. “Every sufficiently advanced API contains an ad hoc, informally- specified

    implementation of some media type on top of JSON.” - Steve Klabnik Getting to JSON:API - Matt Stauffer
  31. APIS ARE A BIKESHEDDER'S PARADISE Getting to JSON:API - Matt

    Stauffer
  32. BIKESHEDDING Wasting time and energy on marginal technical issues. Getting

    to JSON:API - Matt Stauffer
  33. STOP WASTING TIME BIKESHEDDING ON API STANDARDS Getting to JSON:API

    - Matt Stauffer
  34. PART 3 WHAT IS JSON:API? Getting to JSON:API - Matt

    Stauffer
  35. A LITTLE HISTORY: Ember ❤ Rails Getting to JSON:API -

    Matt Stauffer
  36. IT'S A STANDARD Getting to JSON:API - Matt Stauffer

  37. Getting to JSON:API - Matt Stauffer

  38. YOU MAY BE FAMILIAR... { "data": { "type": "articles", "id":

    "1", "attributes": { // ... this article's attributes }, "relationships": { // ... this article's relationships } } } Getting to JSON:API - Matt Stauffer
  39. BUT WHAT ABOUT... ▸ Compound documents in flat included key

    ▸ Content negotiation requirements ▸ Custom error syntax ▸ Nested include directives ▸ Sparse fieldsets ▸ Create/update/delete validation ▸ Relationship modification endpoints Getting to JSON:API - Matt Stauffer
  40. ! Getting to JSON:API - Matt Stauffer

  41. THE BIG PIECES OF JSON:API Getting to JSON:API - Matt

    Stauffer
  42. THE BIG PIECES OF JSON:API ▸ Document structure ▸ HTTP

    standards Getting to JSON:API - Matt Stauffer
  43. THE BIG PIECES PART 1: DOCUMENT STRUCTURE Getting to JSON:API

    - Matt Stauffer
  44. DOCUMENT STRUCTURE IN JSON:API ▸ data ▸ included ▸ links

    ▸ errors ▸ meta ▸ jsonapi Getting to JSON:API - Matt Stauffer
  45. DOCUMENT STRUCTURE IN JSON:API ▸ data ▸ included ▸ links

    ▸ errors ▸ meta ▸ jsonapi Getting to JSON:API - Matt Stauffer
  46. { "jsonapi": { "version": "1.0" }, "meta": { "i can

    do anything": { "i want": ["in", "here"] } } } Getting to JSON:API - Matt Stauffer
  47. DOCUMENT STRUCTURE IN JSON:API ▸ data ▸ included ▸ links

    ▸ errors ▸ meta ▸ jsonapi Getting to JSON:API - Matt Stauffer
  48. { "data": { "type": "articles", "id": "1", } } Getting

    to JSON:API - Matt Stauffer
  49. { "data": [{ "type": "articles", "id": "1" },{ "type": "articles",

    "id": "42" }] } Getting to JSON:API - Matt Stauffer
  50. THE STRUCTURE OF A RESOURCE OBJECT Getting to JSON:API -

    Matt Stauffer
  51. Resource identifier object { "type": "articles", "id": "1" } Getting

    to JSON:API - Matt Stauffer
  52. Optional sections { "type": "articles", "id": "1", "attributes": { //

    key/value pairs of all attributes }, "relationships": { // relationship objects }, "links": { // link objects }, "meta": { // key/value pairs } } Getting to JSON:API - Matt Stauffer
  53. Attributes { "type": "articles", "id": "1", "attributes": { "title": "The

    greatest post ever", "body": "Lorem ipsum" }, } Getting to JSON:API - Matt Stauffer
  54. Relationships { "type": "articles", "id": "1", "relationships": { "author": {

    "data": { "type": "people", "id": "5" } } } } Getting to JSON:API - Matt Stauffer
  55. DOCUMENT STRUCTURE IN JSON:API ▸ data ▸ included ▸ links

    ▸ errors ▸ meta ▸ jsonapi Getting to JSON:API - Matt Stauffer
  56. COMPOUND DOCUMENTS { "data": { "type": "articles", "id": "123", "attributes":

    {}, "relationships": { "author": { "data": { "type": "people", "id": "5" }} } }, "included": [{ "type": "people", "id": "5", "attributes": { "name": "Phil the GOAT" } }] } Getting to JSON:API - Matt Stauffer
  57. DOCUMENT STRUCTURE IN JSON:API ▸ data ▸ included ▸ links

    ▸ errors ▸ meta ▸ jsonapi Getting to JSON:API - Matt Stauffer
  58. LINKS { "data": [{}, {}, {}], "links": { "self": "http://site.com/articles?page=3",

    "first": "http://site.com/articles?page=1", "prev": "http://site.com/articles?page=2", "next": "http://site.com/articles?page=4", "last": "http://site.com/articles?page=42" } } Getting to JSON:API - Matt Stauffer
  59. DOCUMENT STRUCTURE IN JSON:API ▸ data ▸ included ▸ links

    ▸ errors ▸ meta ▸ jsonapi Getting to JSON:API - Matt Stauffer
  60. ERRORS { "errors": [{ "id": "SERVER500C1", "links": {}, "status": "500",

    "code": "SERVER500C1", "title": "A server error has occurred.", "detail": "Longer message here.", "source": { /* Object containing references to the source */}, "meta": {} }] } Getting to JSON:API - Matt Stauffer
  61. ERRORS { "errors": [{ "status": "500", "title": "A server error

    has occurred." }] } Getting to JSON:API - Matt Stauffer
  62. DOCUMENT STRUCTURE IN JSON:API ▸ data ▸ included ▸ links

    ▸ errors ▸ meta ▸ jsonapi Getting to JSON:API - Matt Stauffer
  63. THE BIG PIECES PART 2: HTTP SPECS Getting to JSON:API

    - Matt Stauffer
  64. HTTP SPECS IN JSON:API ▸ Content Negotiation ▸ Verbs &

    Status Codes ▸ Query parameters (include, page, sort, filter, fields) Getting to JSON:API - Matt Stauffer
  65. CONTENT NEGOTIATION Getting to JSON:API - Matt Stauffer

  66. VERBS & STATUS CODES Use them. The way they were

    meant to be used. Note: If a JSON:API feature is requested and you don't support it (e.g. ? include), return a 400 BAD REQUEST Getting to JSON:API - Matt Stauffer
  67. QUERY PARAMETERS ▸ OPINIONATED: ▸ ?include=author,comments.author ▸ ?sort=created_at,-name ▸ ?fields[articles]=title,body&fields[people]=name

    ▸ UNOPINIONATED: ▸ ?page=5 ▸ ?filter[abc]=def Getting to JSON:API - Matt Stauffer
  68. Important note: You don't have to fully adhere to a

    standard to learn from it. Getting to JSON:API - Matt Stauffer
  69. PART 4 WHY JSON:API? Getting to JSON:API - Matt Stauffer

  70. WHY NOT OPENAPI? Getting to JSON:API - Matt Stauffer

  71. WHY NOT GRAPHQL? Getting to JSON:API - Matt Stauffer

  72. JSON:API: "A specification for Fetching and Mutating a Graph of

    Data" — Dan Gebhardt Getting to JSON:API - Matt Stauffer
  73. WHY NOT HAL, SIREN, JSON-LD, COLLECTION+JSON? Getting to JSON:API -

    Matt Stauffer
  74. WHY NOT HTTP/2? Getting to JSON:API - Matt Stauffer

  75. However... Getting to JSON:API - Matt Stauffer

  76. Getting to JSON:API - Matt Stauffer

  77. SO, WHY JSON:API? Stealing from Dan Gebhardt, co-editor of JSON:API:

    Getting to JSON:API - Matt Stauffer
  78. Getting to JSON:API - Matt Stauffer

  79. Getting to JSON:API - Matt Stauffer

  80. PART 5 JSON:API TOOLING IN LARAVEL Getting to JSON:API -

    Matt Stauffer
  81. Which t l should I pick? Getting to JSON:API -

    Matt Stauffer
  82. https://github.com/tightenco/json-api-examples *Totally incomplete examples! Getting to JSON:API - Matt Stauffer

  83. Intro to ELOQUENT RESOURCES FOR JSON API Getting to JSON:API

    - Matt Stauffer
  84. class ArticleResource { public function toArray() { return [ 'data'

    => [ 'type' => 'articles', 'id' => $this->resource->id, ], 'attributes' => [ 'title' => $this->resource->title, ], ]; } } Getting to JSON:API - Matt Stauffer
  85. class ArticleController { public function index() { $articles = QueryBuilder::for(Article::class)

    ->allowedIncludes(['author', 'comments']) ->allowedSorts(['created_at', 'title']) ->paginate(); return new ArticleCollection($articles); } } Getting to JSON:API - Matt Stauffer
  86. Getting to JSON:API - Matt Stauffer

  87. ! Getting to JSON:API - Matt Stauffer

  88. CONCLUSION Good for simple applications, but lots of work for

    full implementation. With Spatie Query Builder, you can get far. But no flat included. Getting to JSON:API - Matt Stauffer
  89. Getting to JSON:API - Matt Stauffer

  90. HOW DO I USE IT? https://github.com/tightenco/json-api-examples/tree/eloquent- resources Getting to JSON:API

    - Matt Stauffer
  91. Intro to FRACTAL FOR JSON API Getting to JSON:API -

    Matt Stauffer
  92. public function index() { $articles = QueryBuilder::for(Article::class) ->allowedIncludes(['author', 'comments']) ->allowedSorts(['created_at',

    'title']) ->paginate(5); return fractal($articles, new ArticleTransformer) ->withResourceName('articles') ->respondJsonApi(); } Getting to JSON:API - Matt Stauffer
  93. class AuthorTransformer extends TransformerAbstract { protected $defaultIncludes = []; protected

    $availableIncludes = ['articles']; public function transform(User $user) { return [ 'id' => (int) $user->id, 'name' => $user->name, ]; } public function includeArticles(User $user) { return $this->collection($user->articles, new ArticleTransformer, 'articles'); } } Getting to JSON:API - Matt Stauffer
  94. CONCLUSION Great for serializing even complex use cases, and great

    if you're a Fractal fan, but there's still manual work to be done. Also requires Spatie Query Builder to get far. Includes flat included for free. Getting to JSON:API - Matt Stauffer
  95. Getting to JSON:API - Matt Stauffer

  96. HOW DO I USE IT? https://github.com/tightenco/json-api-examples/tree/fractal Getting to JSON:API -

    Matt Stauffer
  97. Intro to LARAVEL-JSON-API FOR JSON API Getting to JSON:API -

    Matt Stauffer
  98. class Schema extends SchemaProvider { protected $resourceType = 'articles'; public

    function getId($resource) { return (string) $resource->getRouteKey(); } public function getAttributes($resource) { return [ 'title' => $resource->title, 'body' => $resource->body, ]; } public function getRelationships($resource, $isPrimary, array $includedRelationships) { return [ 'author' => [ self::SHOW_SELF => true, self::SHOW_RELATED => true, self::SHOW_DATA => isset($includedRelationships['author']), self::DATA => function () use ($resource) { return $resource->author; }, Getting to JSON:API - Matt Stauffer
  99. class Adapter extends AbstractAdapter { protected $attributes = []; protected

    $filterScopes = []; protected function author() { return $this->belongsTo('user'); } protected function comments() { return $this->hasMany(); } } Getting to JSON:API - Matt Stauffer
  100. CONCLUSION Steep learning curve, but the best way to get

    even close to full JSON:API. Getting to JSON:API - Matt Stauffer
  101. Getting to JSON:API - Matt Stauffer

  102. HOW DO I USE IT? https://howtojsonapi.com/laravel.html Getting to JSON:API -

    Matt Stauffer
  103. PART 6 OTHER API CONCERNS Getting to JSON:API - Matt

    Stauffer
  104. AUTH ▸ Airlock ▸ Passport ▸ Simple token Getting to

    JSON:API - Matt Stauffer
  105. CACHING ▸ Cache DB requests ▸ Full HTTP request caching

    ▸ Intermediary caching (Varnish, Cloudflare) Getting to JSON:API - Matt Stauffer
  106. PART 7 AFTER THE TALK Getting to JSON:API - Matt

    Stauffer
  107. ▸ Relationship endpoints ▸ True HATEOAS ▸ Etags & cache-control/expires

    ▸ JSON Schema for defining types (client-side validation!) ▸ HTTP/2 Server Push ▸ JSON:API 1.1 Getting to JSON:API - Matt Stauffer
  108. PART 8 OUTRO Getting to JSON:API - Matt Stauffer

  109. TL;DR ▸ API standards are great ▸ JSON:API is a

    great standard ▸ Gradual adoption means there are no judgments! ▸ If you don't adopt something, error if it's asked for ▸ Eloquent Resources/Fractal + Spatie Query Builder for JSON:API lite, Laravel-JSON-API for full spec Getting to JSON:API - Matt Stauffer
  110. RESOURCES Slides, links, and lists at: https://mattstauffer.com/json-api Getting to JSON:API

    - Matt Stauffer