$30 off During Our Annual Pro Sale. View Details »

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

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

Matt Stauffer

February 26, 2020
Tweet

More Decks by Matt Stauffer

Other Decks in Technology

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