Slide 1

Slide 1 text

HOW TO JSON:API QUICKLY & EASILY IN LARAVEL Getting to JSON:API - Matt Stauffer

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

PART 1 Intro to REST APIS Getting to JSON:API - Matt Stauffer

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

REST: CRUD over JSON using HTTP verbs shaped like /dogs/14 and stuff Getting to JSON:API - Matt Stauffer

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

REPRESENTATIONAL STATE TRANSFER Getting to JSON:API - Matt Stauffer

Slide 11

Slide 11 text

ROY FIELDING Getting to JSON:API - Matt Stauffer

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

What's "HATEOAS"? HYPERMEDIA AS THE ENGINE OF APPLICATION STATE Getting to JSON:API - Matt Stauffer

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

APIS AS STATE MACHINES Getting to JSON:API - Matt Stauffer

Slide 21

Slide 21 text

SHOULD WE AIM FOR TRUE HATEOAS? Getting to JSON:API - Matt Stauffer

Slide 22

Slide 22 text

"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

Slide 23

Slide 23 text

SHOULD WE AIM FOR TRUE HATEOAS? PROBABLY NOT. Getting to JSON:API - Matt Stauffer

Slide 24

Slide 24 text

Getting to JSON:API - Matt Stauffer

Slide 25

Slide 25 text

Getting to JSON:API - Matt Stauffer

Slide 26

Slide 26 text

GRADUAL ADOPTION. Getting to JSON:API - Matt Stauffer

Slide 27

Slide 27 text

PART 2 THE STATE OF APIS Getting to JSON:API - Matt Stauffer

Slide 28

Slide 28 text

WE'RE IN THE BAD OLD DAYS WHEN IT COMES TO API STANDARDIZATION Getting to JSON:API - Matt Stauffer

Slide 29

Slide 29 text

Getting to JSON:API - Matt Stauffer

Slide 30

Slide 30 text

“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

Slide 31

Slide 31 text

APIS ARE A BIKESHEDDER'S PARADISE Getting to JSON:API - Matt Stauffer

Slide 32

Slide 32 text

BIKESHEDDING Wasting time and energy on marginal technical issues. Getting to JSON:API - Matt Stauffer

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

Getting to JSON:API - Matt Stauffer

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

! Getting to JSON:API - Matt Stauffer

Slide 41

Slide 41 text

THE BIG PIECES OF JSON:API Getting to JSON:API - Matt Stauffer

Slide 42

Slide 42 text

THE BIG PIECES OF JSON:API ▸ Document structure ▸ HTTP standards Getting to JSON:API - Matt Stauffer

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

{ "jsonapi": { "version": "1.0" }, "meta": { "i can do anything": { "i want": ["in", "here"] } } } Getting to JSON:API - Matt Stauffer

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

{ "data": [{ "type": "articles", "id": "1" },{ "type": "articles", "id": "42" }] } Getting to JSON:API - Matt Stauffer

Slide 50

Slide 50 text

THE STRUCTURE OF A RESOURCE OBJECT Getting to JSON:API - Matt Stauffer

Slide 51

Slide 51 text

Resource identifier object { "type": "articles", "id": "1" } Getting to JSON:API - Matt Stauffer

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

Attributes { "type": "articles", "id": "1", "attributes": { "title": "The greatest post ever", "body": "Lorem ipsum" }, } Getting to JSON:API - Matt Stauffer

Slide 54

Slide 54 text

Relationships { "type": "articles", "id": "1", "relationships": { "author": { "data": { "type": "people", "id": "5" } } } } Getting to JSON:API - Matt Stauffer

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

ERRORS { "errors": [{ "status": "500", "title": "A server error has occurred." }] } Getting to JSON:API - Matt Stauffer

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

THE BIG PIECES PART 2: HTTP SPECS Getting to JSON:API - Matt Stauffer

Slide 64

Slide 64 text

HTTP SPECS IN JSON:API ▸ Content Negotiation ▸ Verbs & Status Codes ▸ Query parameters (include, page, sort, filter, fields) Getting to JSON:API - Matt Stauffer

Slide 65

Slide 65 text

CONTENT NEGOTIATION Getting to JSON:API - Matt Stauffer

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

Important note: You don't have to fully adhere to a standard to learn from it. Getting to JSON:API - Matt Stauffer

Slide 69

Slide 69 text

PART 4 WHY JSON:API? Getting to JSON:API - Matt Stauffer

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

JSON:API: "A specification for Fetching and Mutating a Graph of Data" — Dan Gebhardt Getting to JSON:API - Matt Stauffer

Slide 73

Slide 73 text

WHY NOT HAL, SIREN, JSON-LD, COLLECTION+JSON? Getting to JSON:API - Matt Stauffer

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

Getting to JSON:API - Matt Stauffer

Slide 77

Slide 77 text

SO, WHY JSON:API? Stealing from Dan Gebhardt, co-editor of JSON:API: Getting to JSON:API - Matt Stauffer

Slide 78

Slide 78 text

Getting to JSON:API - Matt Stauffer

Slide 79

Slide 79 text

Getting to JSON:API - Matt Stauffer

Slide 80

Slide 80 text

PART 5 JSON:API TOOLING IN LARAVEL Getting to JSON:API - Matt Stauffer

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

Intro to ELOQUENT RESOURCES FOR JSON API Getting to JSON:API - Matt Stauffer

Slide 84

Slide 84 text

class ArticleResource { public function toArray() { return [ 'data' => [ 'type' => 'articles', 'id' => $this->resource->id, ], 'attributes' => [ 'title' => $this->resource->title, ], ]; } } Getting to JSON:API - Matt Stauffer

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

Getting to JSON:API - Matt Stauffer

Slide 87

Slide 87 text

! Getting to JSON:API - Matt Stauffer

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

Getting to JSON:API - Matt Stauffer

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

Getting to JSON:API - Matt Stauffer

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

CONCLUSION Steep learning curve, but the best way to get even close to full JSON:API. Getting to JSON:API - Matt Stauffer

Slide 101

Slide 101 text

Getting to JSON:API - Matt Stauffer

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

AUTH ▸ Airlock ▸ Passport ▸ Simple token Getting to JSON:API - Matt Stauffer

Slide 105

Slide 105 text

CACHING ▸ Cache DB requests ▸ Full HTTP request caching ▸ Intermediary caching (Varnish, Cloudflare) Getting to JSON:API - Matt Stauffer

Slide 106

Slide 106 text

PART 7 AFTER THE TALK Getting to JSON:API - Matt Stauffer

Slide 107

Slide 107 text

▸ 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

Slide 108

Slide 108 text

PART 8 OUTRO Getting to JSON:API - Matt Stauffer

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

RESOURCES Slides, links, and lists at: https://mattstauffer.com/json-api Getting to JSON:API - Matt Stauffer