示例

本页面包含有关如何应用规范各个部分的更多示例。

稀疏字段集

有关 稀疏字段集 如何工作的示例。

基本请求

GET /articles?include=author HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "data": [{
    "type": "articles",
    "id": "1",
    "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"
    },
    "relationships": {
      "author": {
        "data": {"id": "42", "type": "people"}
      }
    }
  }],
  "included": [
    {
      "type": "people",
      "id": "42",
      "attributes": {
        "name": "John",
        "age": 80,
        "gender": "male"
      }
    }
  ]
}

带有 fields[articles]fields[people] 参数的请求

GET /articles?include=author&fields[articles]=title,body,author&fields[people]=name HTTP/1.1

注意:以上示例 URI 显示未编码的 [] 字符,仅为可读性。在实践中,应按基础规范中的说明对这些字符进行百分比编码。请参阅“参数名称中的方括号”。

这里我们希望 articles 对象仅具有字段 titlebodyauthor,而 people 对象仅具有 name 字段。

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my bikeshed!",
      "body": "The shortest article. Ever."
    },
    "relationships": {
      "author": {
        "data": {"id": "42", "type": "people"}
      }
    }
  }],
  "included": [
    {
      "type": "people",
      "id": "42",
      "attributes": {
        "name": "John"
      }
    }
  ]
}

请注意,您必须在 includefields 中添加关系名称(因为关系也是字段),否则您将获得

GET /articles?include=author&fields[articles]=title,body&fields[people]=name HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my bikeshed!",
      "body": "The shortest article. Ever."
    }
  }],
  "included": [
    {
      "type": "people",
      "id": "42",
      "attributes": {
        "name": "John"
      }
    }
  ]
}

注意:以上示例 URI 显示未编码的 [] 字符,仅为可读性。在实践中,应按基础规范中的说明对这些字符进行百分比编码。请参阅“参数名称中的方括号”。

有关如何添加 分页链接 的基于页面的策略示例。

基本请求

GET /articles?page[number]=3&page[size]=1 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "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"
  }
}

注意:以上示例 URI 显示未编码的 [] 字符,仅为可读性。在实践中,应按基础规范中的说明对这些字符进行百分比编码。请参阅“参数名称中的方括号”。

注意:将诸如 "totalPages" 之类的属性放在 "meta" 中可以是方便地向客户端指示集合中总页数的一种方式(与 "last" 链接相反,后者只给出最后一页的 URI)。但是,所有 "meta" 值都是特定于实现的,因此您可以随意调用此成员("total""count" 等),也可以完全不使用它。

错误对象

有关 错误对象 如何工作的示例。

基本错误对象

在以下响应中,服务器表示在创建/更新资源时遇到了错误,并且该错误是由无效的 "firstName" 属性引起的

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 two characters."
    }
  ]
}

错误对象中的每个成员都是可选的,但它们都有助于通过提供更多详细信息来帮助客户端。

source 成员用于 指示请求文档的哪一部分导致了错误。

titledetail 成员类似,但 detail 特定于此问题的发生,而 title 更通用。

status 成员表示与问题关联的 HTTP 状态代码。当一次返回多个错误时(见下文),它非常有用,因为 HTTP 响应本身只能有一个状态代码。但是,它对于单个错误也很有用,可以避免客户端查看 HTTP 标头,或者在将 JSON:API 用于未来可能正式支持的非 HTTP 协议时。

多个错误

当单个请求响应中出现多个错误时,服务器只需将每个错误添加到 errors 数组中

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."
    }
  ]
}

错误对象上唯一的唯一性约束是 id 字段。因此,同一属性上的多个错误可以分别给出自己的错误对象。以下示例显示了 "firstName" 属性上的多个错误

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

{
  "errors": [
    {
      "source": { "pointer": "/data/attributes/firstName" },
      "title": "Invalid Attribute",
      "detail": "First name must contain at least two characters."
    },
    {
      "source": { "pointer": "/data/attributes/firstName" },
      "title": "Invalid Attribute",
      "detail": "First name must contain an emoji."
    }
  ]
}

注意:在以上带有 422 状态代码的响应中,400 Bad Request 也是可以接受的。(更多详细信息。)JSON:API 对 400 与 422 不持立场。

错误代码

错误对象的 code 成员包含表示所遇到的问题类型的特定于应用程序的代码。 codetitle 类似,因为两者都标识了一种通用的问题类型(与 detail 不同,后者特定于问题的特定实例),但是通过编程方式处理 code 比较容易,因为由于本地化,“相同”的 title 可能以不同的形式出现。

对于以下示例,假设 API 文档指定了以下映射

代码 问题
123 值太短
225 密码缺少字母、数字或标点符号
226 密码不匹配
227 密码不能是最近五个密码之一

"password" 属性上的多个错误,错误 code

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

{
  "jsonapi": { "version": "1.1" },
  "errors": [
    {
      "code":   "123",
      "source": { "pointer": "/data/attributes/firstName" },
      "title":  "Value is too short",
      "detail": "First name must contain at least two characters."
    },
    {
      "code":   "225",
      "source": { "pointer": "/data/attributes/password" },
      "title": "Passwords must contain a letter, number, and punctuation character.",
      "detail": "The password provided is missing a punctuation character."
    },
    {
      "code":   "226",
      "source": { "pointer": "/data/attributes/password" },
      "title": "Password and password confirmation do not match."
    }
  ]
}

注意,此响应不仅包含 errors 顶级成员,还包含 jsonapi 顶级成员。错误响应不能包含顶级 data 成员,但可以包含 JSON:API 定义的所有其他顶级成员。

另外,请注意,第三个错误对象缺少 detail 成员(可能是出于安全原因)。同样,所有错误对象成员都是可选的。

高级 source 用法

在以下示例中,用户正在发送一个无效的 JSON:API 请求,因为它缺少 data 成员

PATCH /posts/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{ "datum": [ ] }

因此,服务器响应

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

{
  "errors": [
    {
      "source": { "pointer": "" },
      "detail":  "Missing `data` Member at document's top level."
    }
  ]
}

它使用 source 指向文档的顶层 ("")。(指向“/”将是对请求文档 {"": "some value"} 中的字符串 "some value" 的适当引用。指向 "/data" 将是无效的,因为请求文档在 "/data" 上没有值,并且 source 始终是相对于请求文档给出的。)

如果服务器无法将请求解析为有效的 JSON,包括 source 就没有意义(因为没有 JSON 文档供 source 引用)。以下是如何让服务器对无效的 JSON 文档做出响应

{
  "errors": [{
    "status": "400",
    "detail": "JSON parse error - Expecting property name at line 1 column 2 (char 1)."
  }]
}

无效的查询参数

source 成员还可以用于指示错误源于 URI 查询参数问题,如下所示

GET /api/posts/1?include=author HTTP/1.1
HTTP/1.1 400 Bad Request
Content-Type: application/vnd.api+json

{
  "errors": [
    {
      "source": { "parameter": "include" },
      "title":  "Invalid Query Parameter",
      "detail": "The resource does not have an `author` relationship path."
    }
  ]
}

在大多数情况下,JSON:API 要求服务器在遇到 JSON:API 定义的查询参数的无效值时返回错误。但是,对于特定于 API 的查询参数(即,JSON:API 未定义的查询参数),服务器可以选择忽略无效参数并让请求成功,而不是返回错误。特定于 API 的查询参数必须包含一个非 a-z 字符。

其他无效参数示例包括:?fields[people]=(无效参数名称;应该是 fields[people])和 ?redirect_to=http%3A%2F%2Fwww.owasp.org(无效参数,在本例中为网络钓鱼攻击)等。