JSON API - fantasy0107/notes GitHub Wiki

json api
Laravel 5.5 用 resource 表現出 json api

Document Structure

Top Level - 至少有下面其中一項

//MUST

  1. data - the document’s “primary data”

  2. errors - an array of error objects

  3. meta - a meta object that contains non-standard meta-information

  4. a single resource object - a single resource identifier object / null

//Resource Objects
MUST  
1. id (string)
2. type (string)
MAY 
1. attributes
2. relationships
3. links
4. meta

{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      // ... this article's attributes
    },
    "relationships": {
      // ... this article's relationships
    }
  }
}

{
  "data": {
    "type": "articles",
    "id": "1"
  }
}

Fetching Data

fields Sorting

/people?sort=age 
/people?sort=age,name
/articles?sort=-created,title

Pagination

GET /articles?page[number]=3&page[size]=1 HTTP/1.1
{
  "meta": {
    "totalPages": 13
  },
  "data": [
    {
      "type": "articles",
      "id": "3",
      "attributes": {
        "title": "JSON:API paints my bikeshed!",
        "body": "The shortest article. Ever.",
        "created": "2015-05-22T14:56:29.000Z",
        "updated": "2015-05-22T14:56:28.000Z"
      }
    }
  ],
  "links": {
    "self": "http://example.com/articles?page[number]=3&page[size]=1",
    "first": "http://example.com/articles?page[number]=1&page[size]=1",
    "prev": "http://example.com/articles?page[number]=2&page[size]=1",
    "next": "http://example.com/articles?page[number]=4&page[size]=1",
    "last": "http://example.com/articles?page[number]=13&page[size]=1"
  }
}

Filtering

// 200
{
  "links": {
    "self": "http://example.com/articles/1"
  },
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my bikeshed!"
    },
    "relationships": {
      "author": {
        "links": {
          "related": "http://example.com/articles/1/author"
        }
      }
    }
  }
}

Creating Resources

// POST /photos HTTP/1.1
{
  "data": {
    "type": "photos",
    "attributes": {
      "title": "Ember Hamster",
      "src": "http://example.com/images/productivity.png"
    },
    "relationships": {
      "photographer": {
        "data": { "type": "people", "id": "9" }
      }
    }
  }
}

Updating Resources

PATCH /articles/1 HTTP/1.1
{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "To TDD or Not"
    }
  }
}

Deleting Resources

DELETE /photos/1 HTTP/1.1

Error Objects

id -  a unique identifier for this particular occurrence of the problem.
links - a links object containing the following members
status - the HTTP status code applicable to this problem, expressed as a string value
code - an application-specific error code, expressed as a string value
title - a short, human-readable summary of the problem that SHOULD NOT change from occurrence to occurrence of the problem
detail - a human-readable explanation specific to this occurrence of the problem
source - an object containing references to the source of the error, optionally including any of the following members
meta - a meta object containing non-standard meta-information about the error

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/vnd.api+json

//單一
{
  "errors": [
    {
      "status": "422",
      "source": { "pointer": "/data/attributes/firstName" },
      "title":  "Invalid Attribute",
      "detail": "First name must contain at least three characters."
    }
  ]
}

//multiple
HTTP/1.1 400 Bad Request
Content-Type: application/vnd.api+json

{
  "errors": [
    {
      "status": "403",
      "source": { "pointer": "/data/attributes/secretPowers" },
      "detail": "Editing secret powers is not authorized on Sundays."
    },
    {
      "status": "422",
      "source": { "pointer": "/data/attributes/volume" },
      "detail": "Volume does not, in fact, go to 11."
    },
    {
      "status": "500",
      "source": { "pointer": "/data/attributes/reputation" },
      "title": "The backend responded with an error",
      "detail": "Reputation service not responding after three requests."
    }
  ]
}
  1. an array of resource objects - an array of resource identifier objects, or an empty array ([])

errors - an array of error objects
meta - a meta object that contains non-standard meta-information

//MAY jsonapi - an object describing the server’s implementation
links - a links object related to the primary data
或許會有

  1. self - the link that generated the current response document.
  2. related - a related resource link when the primary data represents a resource relationship

included - an array of resource objects that are related to the primary data and/or each other

{
    "data": [
        {
            "type": "articles",
            "id": "1",
            "attributes": {
                "title": "JSON API paints my bikeshed!"
            },
            "relationships": {
                "author": {
                    "links": {
                        "self": "http://127.0.0.1:8000/api/articles/1/relationships/author",
                        "related": "http://127.0.0.1:8000/api/articles/1/author"
                    },
                    "data": {
                        "type": "people",
                        "id": "9"
                    }
                },
                "comments": {
                    "data": [
                        {
                            "type": "comments",
                            "id": "5"
                        },
                        {
                            "type": "comments",
                            "id": "9"
                        }
                    ],
                    "links": {
                        "self": "http://127.0.0.1:8000/api/articles/1/relationships/comments",
                        "related": "http://127.0.0.1:8000/api/articles/1/comments"
                    }
                }
            },
            "links": {
                "self": "http://127.0.0.1:8000/api/articles/1"
            }
        }
    ],
    "links": {
        "first": "http://127.0.0.1:8000/api/articles?page=1",
        "last": "http://127.0.0.1:8000/api/articles?page=1",
        "prev": null,
        "next": null,
        "self": "http://127.0.0.1:8000/api/articles"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://127.0.0.1:8000/api/articles",
        "per_page": 15,
        "to": 1,
        "total": 1
    },
    "included": [
        {
            "type": "people",
            "id": "9",
            "attributes": {
                "first-name": "Dan",
                "last-name": "Gebhardt",
                "twitter": "dgeb"
            },
            "links": {
                "self": "http://127.0.0.1:8000/api/authors/9"
            }
        },
        {
            "type": "comments",
            "id": "5",
            "attributes": {
                "body": "First!"
            },
            "relationships": {
                "author": {
                    "data": {
                        "type": "people",
                        "id": "2"
                    }
                }
            },
            "links": {
                "self": "http://127.0.0.1:8000/api/comments/5"
            }
        },
        {
            "type": "comments",
            "id": "9",
            "attributes": {
                "body": "I like XMP better"
            },
            "relationships": {
                "author": {
                    "data": {
                        "type": "people",
                        "id": "9"
                    }
                }
            },
            "links": {
                "self": "http://127.0.0.1:8000/api/comments/9"
            }
        }
    ]
}