JSON API最新规范 (v1.0)

JSON:API — Latest Specification (v1.0)

最新规范 (v1.0)

状态

本页展示了 JSON:API 的最新发布版本,目前是 1.0 版。新版本的 JSON:API将始终使用永不删除,仅添加策略向后兼容。可以在我们的讨论区提出补充。

如果您在规范文本中发现错误,或者您编写了实现,请通过在我们的 GitHub 存储库中打开问题或拉取请求来告知我们。

介绍

JSON:API 是关于客户端应如何请求获取或修改资源以及服务器应如何响应这些请求的规范。

JSON:API 旨在最大限度地减少请求数量以及客户端和服务器之间传输的数据量。这种效率是在不影响可读性、灵活性或可发现性的情况下实现的。

JSON:API 需要使用 JSON:API 媒体类型 ( application/vnd.api+json) 来交换数据。

约定

本文档中的关键词“必须”、“不得”、“要求”、“应”、“不应”、“应该”、“不应”、“推荐”、“可以”和“可选”是按照 RFC 2119 [ RFC2119 ]中的描述进行解释。

内容协商

客户责任

客户端必须在请求文档中发送所有 JSON:API 数据,其标头 Content-Type: application/vnd.api+json不带任何媒体类型参数。

Accept在其标头中包含 JSON:API 媒体类型的客户端必须 在其中至少指定一次媒体类型,而无需任何媒体类型参数。

客户端必须忽略响应文档标头中application/vnd.api+json 接收到的媒体类型的任何参数。Content-Type

服务器职责

服务器必须在响应文档中发送所有 JSON:API 数据,其标头 Content-Type: application/vnd.api+json不带任何媒体类型参数。

如果请求指定 带有任何媒体类型参数的标头,服务器必须以状态码响应。415 Unsupported Media TypeContent-Type: application/vnd.api+json

如果请求的标头包含 JSON:API 媒体类型,并且该媒体类型的所有实例都使用媒体类型参数进行了修改,则服务器必须使用状态代码进行响应。406 Not AcceptableAccept

注意:存在内容协商要求以允许本规范的未来版本使用媒体类型参数进行扩展协商和版本控制。

文件结构

本节介绍 JSON:API 文档的结构,由 media type 标识application/vnd.api+json。JSON:API 文档在 JavaScript Object Notation (JSON) [ RFC7159 ] 中定义。

尽管请求和响应文档都使用相同的媒体类型,但某些方面仅适用于其中之一。这些差异在下面列出。

除非另有说明,否则本规范定义的对象不得 包含任何附加成员。客户端和服务器实现必须 忽略本规范无法识别的成员。

注意:这些条件允许本规范通过附加更改而发展。

顶层

JSON 对象必须位于每个 JSON:API 请求和包含数据的响应的根。这个对象定义了一个文档的“顶层”。

文档必须至少包含以下顶级成员之一:

成员dataerrors 不得共存于同一个文档中。

一个文档可以包含这些顶级成员中的任何一个:

  • jsonapi: 描述服务器实现的对象
  • links:与原始数据相关的链接对象。
  • included:与原始数据和/或彼此相关的资源对象数组(“包含的资源”)。

如果文档不包含顶级data键,则该included成员 也不得出现。

顶级链接对象 可以包含以下成员:

文档的“主要数据”是请求所针对的资源或资源集合的表示。

主要数据必须是:

例如,以下主要数据是单个资源对象:

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

以下主要数据是引用同一资源的单个资源标识符对象

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

资源的逻辑集合必须表示为一个数组,即使它只包含一项或为空。

资源对象

“资源对象”出现在 JSON:API 文档中以表示资源。

资源对象必须至少包含以下顶级成员:

  • id
  • type

例外:id当资源对象源自客户端并表示要在服务器上创建的新资源时,不需要该成员。

此外,资源对象可以包含以下任何顶级成员:

  • attributes: 表示资源的一些数据的属性对象
  • relationships:描述资源和其他 JSON:API 资源之间关系的关系对象。
  • links:一个链接对象,包含与资源相关的链接。
  • meta:一个元对象,包含有关资源的非标准元信息,不能表示为属性或关系。

以下是一篇文章(即“文章”类型的资源)在文档中的显示方式:

// ...
{
  "type": "articles",
  "id": "1",
  "attributes": {
    "title": "Rails is Omakase"
  },
  "relationships": {
    "author": {
      "links": {
        "self": "/articles/1/relationships/author",
        "related": "/articles/1/author"
      },
      "data": { "type": "people", "id": "9" }
    }
  }
}
// ...

鉴别

每个资源对象 必须包含一个id成员和一个type成员。idtype成员的值必须是字符串。

在给定的 API 中,每个资源对象typeid必须 标识一个唯一的资源。(由一个服务器控制的一组 URI,或作为一个服务器的多个服务器构成一个 API。)

type成员用于描述共享共同属性和关系的资源对象

type成员的值必须遵守与成员名称相同的约束 。

注意:本规范与变形规则无关,因此 的值type 可以是复数或单数。但是,应在整个实现过程中始终使用相同的值。

字段

资源对象的属性及其关系统称为其“字段”。

资源对象 的字段必须彼此共享一个公共命名空间,并与type和共享id。换句话说,资源不能有同名的属性和关系,也不能有名为typeor的属性或关系id

属性

attributes键的值必须是一个对象(一个“属性对象”)。属性对象(“属性”)的成员表示有关定义它的资源对象的信息。

属性可以包含任何有效的 JSON 值。

涉及 JSON 对象和数组的复杂数据结构允许作为属性值。但是,任何构成或包含在属性中的对象都不得包含relationshipsorlinks成员,因为这些成员由本规范保留以供将来使用。

尽管只有一个外键(例如author_id)通常与要在资源对象中表示的其他信息一起存储在内部,但这些键 不应显示为属性。

注意:有关此容器的更多限制,请参阅字段成员名称

关系

relationships键的值必须是一个对象(“关系对象”)。关系对象(“关系”)的成员表示从定义它的资源对象到其他资源对象的引用。

关系可以是一对一或一对多。

“关系对象”必须至少包含以下内容之一:

  • links: 一个至少包含以下内容之一的 链接对象:
    • self:关系本身的链接(“关系链接”)。该链接允许客户直接操纵关系。例如,删除一个authorthrougharticle的关系 URL 会断开此人与 的连接,article而不会删除people资源本身。获取成功后,此链接返回相关资源的链接 作为其主要数据。(请参阅获取关系。)
    • related:相关资源链接
  • data:资源联动
  • meta:一个元对象,包含有关关系的非标准元信息。

表示一对多关系的关系对象也可以在成员下包含 分页链接links,如下所述。关系对象中的任何 分页链接必须分页关系数据,而不是相关资源。

注意:有关此容器的更多限制,请参阅字段成员名称

相关资源链接

“相关资源链接”提供对 在关系中链接的资源对象 的访问。获取时,相关资源对象将作为响应的主要数据返回。

例如,articlecomments 关系可以指定一个链接,该链接 在通过请求检索时返回评论资源对象的集合。GET

如果存在,相关的资源链接必须引用一个有效的 URL,即使该关系当前没有与任何目标资源相关联。此外,相关资源链接不得因为其关系的内容发生变化而发生变化。

资源联动

复合文档中的资源链接允许客户端将所有包含的资源对象链接在一起,而无需通过链接GET访问任何 URL 。

资源链接必须表示为以下之一:

注意:该规范没有赋予多对多关系链接数组中资源标识符对象的顺序含义,尽管实现可能会这样做。资源标识符对象的数组可以表示有序或无序的关系,并且这两种类型可以混合在一个响应对象中。

例如,以下文章与一个相关联author

// ...
{
  "type": "articles",
  "id": "1",
  "attributes": {
    "title": "Rails is Omakase"
  },
  "relationships": {
    "author": {
      "links": {
        "self": "http://example.com/articles/1/relationships/author",
        "related": "http://example.com/articles/1/author"
      },
      "data": { "type": "people", "id": "9" }
    }
  },
  "links": {
    "self": "http://example.com/articles/1"
  }
}
// ...

关系包括关系本身的author链接(允许客户端直接更改相关作者)、用于获取资源对象的相关资源链接和链接信息。

资源链接

每个资源对象中的可选links成员包含与资源相关的链接 。

如果存在,此链接对象可能包含一个self 链接,该链接标识由资源对象表示的资源。

// ...
{
  "type": "articles",
  "id": "1",
  "attributes": {
    "title": "Rails is Omakase"
  },
  "links": {
    "self": "http://example.com/articles/1"
  }
}
// ...

服务器必须GET使用包含资源作为主要数据的响应来响应对指定 URL的请求。

资源标识符对象

“资源标识符对象”是标识单个资源的对象。

“资源标识符对象”必须包含typeid成员。

“资源标识符对象”还可以包括一个meta成员,其值为包含非标准元信息的元对象。

复合文件

为了减少 HTTP 请求的数量,服务器可以允许响应包括相关资源以及请求的主要资源。此类响应称为“复合文档”。

在复合文档中,所有包含的资源必须表示为顶级成员中的资源对象数组included

复合文档需要“完全链接”,这意味着每个包含的资源必须由 同一文档中的至少一个资源标识符对象标识。这些资源标识符对象可以是主要数据或表示包含在主要或包含的资源中的资源链接。

完整链接要求的唯一例外是通过稀疏字段集排除原本包含链接数据的关系字段。

注意:完全链接确保包含的资源与主要数据(可能是资源对象资源标识符对象)或彼此相关。

具有多个包含关系的完整示例文档:

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my bikeshed!"
    },
    "links": {
      "self": "http://example.com/articles/1"
    },
    "relationships": {
      "author": {
        "links": {
          "self": "http://example.com/articles/1/relationships/author",
          "related": "http://example.com/articles/1/author"
        },
        "data": { "type": "people", "id": "9" }
      },
      "comments": {
        "links": {
          "self": "http://example.com/articles/1/relationships/comments",
          "related": "http://example.com/articles/1/comments"
        },
        "data": [
          { "type": "comments", "id": "5" },
          { "type": "comments", "id": "12" }
        ]
      }
    }
  }],
  "included": [{
    "type": "people",
    "id": "9",
    "attributes": {
      "first-name": "Dan",
      "last-name": "Gebhardt",
      "twitter": "dgeb"
    },
    "links": {
      "self": "http://example.com/people/9"
    }
  }, {
    "type": "comments",
    "id": "5",
    "attributes": {
      "body": "First!"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "2" }
      }
    },
    "links": {
      "self": "http://example.com/comments/5"
    }
  }, {
    "type": "comments",
    "id": "12",
    "attributes": {
      "body": "I like XML better"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "9" }
      }
    },
    "links": {
      "self": "http://example.com/comments/12"
    }
  }]
}

一个复合文档 不能为每个和对包含一个以上的资源对象。typeid

注意:在单个文档中,您可以将typeandid视为唯一引用文档另一部分中的资源对象的复合键。

注意:此方法可确保每个响应都返回一个规范资源对象,即使多次引用同一资源也是如此。

元信息

在指定的情况下,meta成员可用于包含非标准元信息。每个meta成员的值必须是一个对象(“元对象”)。

可以meta对象中指定任何成员。

例如:

{
  "meta": {
    "copyright": "Copyright 2015 Example Corp.",
    "authors": [
      "Yehuda Katz",
      "Steve Klabnik",
      "Dan Gebhardt",
      "Tyler Kellen"
    ]
  },
  "data": {
    // ...
  }
}

如果指定,links成员可用于表示链接。每个links成员的值必须是一个对象(“链接对象”)。

链接对象的每个成员都是一个“链接”。链接必须表示为:

  • 包含链接 URL 的字符串。
  • 可以包含以下成员的对象(“链接对象”):
    • href: 包含链接 URL 的字符串。
    • meta:一个元对象,包含有关链接的非标准元信息。

以下self链接只是一个 URL:

"links": {
  "self": "http://example.com/posts"
}

以下related链接包括一个 URL 以及有关相关资源集合的元信息:

"links": {
  "related": {
    "href": "http://example.com/articles/1/comments",
    "meta": {
      "count": 10
    }
  }
}

注意:将来可能会为链接对象和链接对象指定其他成员。也有可能扩展其他成员的允许值(例如,collection链接可能支持值数组,而self链接不支持)。

JSON:API 对象

JSON:API 文档可以包含有关其在顶级jsonapi成员下的实现的信息。如果存在,则jsonapi 成员的值必须是一个对象(“jsonapi 对象”)。jsonapi 对象可以 包含一个version成员,其值是一个字符串,表示支持的最高 JSON API 版本。这个对象也可以包含一个meta成员,它的值是一个包含非标准元信息的元对象。

{
  "jsonapi": {
    "version": "1.0"
  }
}

如果该version成员不存在,则客户端应假定服务器至少实现了规范的 1.0 版。

注意:因为 JSON:API 只承诺进行附加更改,所以版本字符串主要指示服务器可能支持哪些新功能。

会员姓名

JSON:API 文档中使用的所有成员名称必须被客户端和服务器视为区分大小写,并且它们必须满足以下所有条件:

  • 成员名称必须至少包含一个字符。
  • 成员名称必须仅包含下面列出的允许字符。
  • 成员名称必须以“全局允许的字符”开头和结尾,定义如下。

为了能够轻松地将成员名称映射到 URL,建议成员名称仅使用RFC 3986中指定的非保留的 URL 安全字符。

允许的字符

以下“全局允许的字符”可以在成员名称的任何地方使用:

  • U+0061 至 U+007A,“az”
  • U+0041 至 U+005A,“AZ”
  • U+0030 至 U+0039,“0-9”
  • U+0080 及以上(非 ASCII Unicode 字符;不推荐,不是 URL 安全的)

此外,成员名称中允许使用以下字符,第一个或最后一个字符除外:

  • U+002D 连字符-减号,“-”
  • U+005F 低线,“_”
  • U+0020 SPACE,“” (不推荐,不是 URL 安全的)

保留字符

成员名称中不得使用以下字符:

  • U+002B 加号,“+” (用于订购)
  • U+002C 逗号,“,” (用作关系路径之间的分隔符)
  • U+002E 句号,“.” (用作关系路径中的分隔符)
  • U+005B 左方括号,“[” (用于稀疏字段集中)
  • U+005D 右方括号,“]” (用于稀疏字段集)
  • U+0021 感叹号,“!”
  • U+0022 引号, '”'
  • U+0023 数字符号,“#”
  • U+0024 美元符号,“$”
  • U+0025 百分号,“%”
  • U+0026 与号,“&”
  • U+0027 撇号,“'”
  • U+0028 左括号,“(”
  • U+0029 右括号,“)”
  • U+002A 星号,“*”
  • U+002F 固体,“/”
  • U+003A 冒号,“:”
  • U+003B 分号,“;”
  • U+003C 小于号,“<”
  • U+003D 等号,“=”
  • U+003E 大于号,“>”
  • U+003F 问号,“?”
  • U+0040 商业地址,“@”
  • U+005C 反向固定,“\”
  • U+005E 循环重音,“^”
  • U+0060 重音,“`”
  • U+007B 左大括号,“{”
  • U+007C 垂直线,“|”
  • U+007D 右花括号,“}”
  • U+007E 波浪号,“~”
  • U+007F 删除
  • U+0000 到 U+001F(C0 控制)

获取数据

GET可以通过向端点发送请求来获取数据,包括资源和关系 。

可以使用下面描述的可选功能进一步细化响应。

获取资源

服务器必须支持为每个提供的 URL 获取资源数据:

  • 作为self顶级链接对象一部分的链接
  • 作为self资源级链接对象一部分的链接
  • 作为related关系级链接对象一部分的链接

例如,以下请求获取文章集合:

GET /articles HTTP/1.1
Accept: application/vnd.api+json

以下请求获取一篇文章:

GET /articles/1 HTTP/1.1
Accept: application/vnd.api+json

以下请求获取文章的作者:

GET /articles/1/author HTTP/1.1
Accept: application/vnd.api+json

回应

200 好

服务器必须响应成功的请求以获取单个资源或资源集合并返回200 OK响应。

服务器必须响应成功的请求以获取资源集合,其中包含资源对象数组或空数组 ( []) 作为响应文档的主要数据。

例如,GET对文章集合的请求可能会返回:

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

{
  "links": {
    "self": "http://example.com/articles"
  },
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my bikeshed!"
    }
  }, {
    "type": "articles",
    "id": "2",
    "attributes": {
      "title": "Rails is Omakase"
    }
  }]
}

代表空集合的类似响应是:

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

{
  "links": {
    "self": "http://example.com/articles"
  },
  "data": []
}

服务器必须响应成功的请求以使用资源对象获取单个资源或null作为响应文档的主要数据提供。

null仅当请求的 URL 可能对应于单个资源但当前不对应时,它才是适当的响应。

注意:例如,考虑一个获取一对一相关资源链接的请求。null当关系为空时(例如链接不对应于任何资源), 此请求将响应,否则将响应单个相关资源的资源对象

例如,GET对单个文章的请求可能会返回:

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

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

如果缺少上述文章的作者,则GET对该相关资源的请求将返回:

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

{
  "links": {
    "self": "http://example.com/articles/1/author"
  },
  "data": null
}

404 未找到

当处理请求以获取不存在的单个资源时, 服务器必须响应,除非请求保证响应作为主要数据(如上所述)。404 Not Found200 OKnull

其他回应

服务器可以使用其他 HTTP 状态代码进行响应。

服务器可以包含带有错误响应的错误详细信息。

服务器必须准备响应,客户端必须根据 HTTP semantics.

获取关系

服务器必须支持获取作为关系对象self一部分的链接提供的每个关系 URL 的关系数据。links

例如,以下请求获取有关文章评论的数据:

GET /articles/1/relationships/comments HTTP/1.1
Accept: application/vnd.api+json

以下请求获取有关文章作者的数据:

GET /articles/1/relationships/author HTTP/1.1
Accept: application/vnd.api+json

回应

200 好

服务器必须响应成功的请求以获取与200 OK响应的关系。

响应文档中的主要数据必须与资源链接的适当值相匹配,如上文对 关系对象所述。

顶级链接对象 可以包含selfrelated链接,如上文对关系对象所述。

例如,GET从一对一关系链接对 URL 的请求可能会返回:

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

{
  "links": {
    "self": "/articles/1/relationships/author",
    "related": "/articles/1/author"
  },
  "data": {
    "type": "people",
    "id": "12"
  }
}

如果上述关系为空,则GET对同一 URL 的请求将返回:

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

{
  "links": {
    "self": "/articles/1/relationships/author",
    "related": "/articles/1/author"
  },
  "data": null
}

GET从一对多关系链接对 URL的请求可能会返回:

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

{
  "links": {
    "self": "/articles/1/relationships/tags",
    "related": "/articles/1/tags"
  },
  "data": [
    { "type": "tags", "id": "2" },
    { "type": "tags", "id": "3" }
  ]
}

如果上述关系为空,则GET对同一 URL 的请求将返回:

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

{
  "links": {
    "self": "/articles/1/relationships/tags",
    "related": "/articles/1/tags"
  },
  "data": []
}

404 未找到

处理请求以获取不存在的关系链接 URL 时,服务器必须返回。404 Not Found

注意:当关系的父资源不存在时,可能会发生这种情况。例如,/articles/1不存在时,请求 /articles/1/relationships/tags返回404 Not Found

如果存在关系链接 URL 但关系为空,则 200 OK 必须返回,如上所述。

其他回应

服务器可以使用其他 HTTP 状态代码进行响应。

服务器可以包含带有错误响应的错误详细信息。

服务器必须准备响应,客户端必须根据 HTTP semantics.

默认情况下,端点可以返回与原始数据相关的资源。

端点也可以支持include请求参数以允许客户端自定义应返回哪些相关资源。

如果端点不支持该include参数,它必须响应400 Bad Request任何包含它的请求。

如果端点支持该include参数并且客户端提供它,则服务器不得在复合文档的 部分中包含未请求的资源对象included

include参数的值必须是一个以逗号分隔(U+002C COMMA, “,”)的关系路径列表。关系路径是一个以点分隔(U+002E 句号,“.”)的关系名称列表。

如果服务器无法识别关系路径或不支持包含来自路径的资源,它必须以 400 Bad Request 响应。

注意:例如,关系路径可以是comments.author,其中 comments是资源对象下列articles 的关系,并且 author是资源对象下列出的comments 关系

例如,可以通过文章请求评论:

GET /articles/1?include=comments HTTP/1.1
Accept: application/vnd.api+json

为了请求与其他资源相关的资源,可以为每个关系名称指定一个点分隔的路径:

GET /articles/1?include=comments.author HTTP/1.1
Accept: application/vnd.api+json

注意:由于复合文档需要全链接(除非是稀疏字段集排除了关系链接),因此多部分路径中的中间资源必须与叶节点一起返回。例如,对请求的响应comments.author应该包括comments 以及其中author的每一个comments

注意:服务器可以选择公开深层嵌套关系,例如 comments.author与别名的直接关系,例如 comment-authors. 这将允许客户端请求 /articles/1?include=comment-authors而不是 /articles/1?include=comments.author. 通过使用别名抽象嵌套关系,服务器仍然可以在复合文档中提供完整的链接,而不包括潜在的不需要的中间资源。

可以在逗号分隔的列表中请求多个相关资源:

GET /articles/1?include=author,comments.author HTTP/1.1
Accept: application/vnd.api+json

此外,可以从关系端点请求相关资源:

GET /articles/1/relationships/comments?include=comments.author HTTP/1.1
Accept: application/vnd.api+json

在这种情况下,主要数据将是 资源标识符对象的集合,这些对象表示与文章评论的链接,而完整的评论和评论作者将作为包含的数据返回。

注意:本节适用于使用主要数据响应的任何端点,无论请求类型如何。例如,服务器可以支持包含相关资源以及POST创建资源或关系的请求。

稀疏字段集

客户端可以通过包含参数来请求端点在每种类型的基础上仅返回响应中的特定字段。fields[TYPE]

fields参数的值必须是一个逗号分隔的 (U+002C COMMA, “,”) 列表,表示要返回的字段的名称。空值表示不应返回任何字段。

如果客户端请求给定资源类型的一组受限字段,端点不得在其响应中包含该类型资源对象中的附加字段

如果客户端没有为给定的资源类型指定字段集,服务器可以发送该资源类型的所有字段、字段子集或不发送任何字段。

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

注意:上面的示例 URI 显示未编码[]字符只是为了便于阅读。在实践中,这些字符必须按照RFC 3986 中的要求进行百分比编码。

注意:本节适用于以资源作为主要数据或包含数据进行响应的任何端点,无论请求类型如何。例如,服务器可以支持稀疏字段集以及POST创建资源的请求。

排序

服务器可以选择支持根据一个或多个标准(“排序字段”)对资源集合进行排序的请求。

注意:虽然推荐,但排序字段不一定需要对应于资源属性和关联名称。

注意:建议使用点分隔(U+002E FULL-STOP,“.”)排序字段来请求基于关系属性的排序。例如,排序字段author.name可用于请求根据关系的name属性对主要数据进行排序author 。

端点可以支持使用sort 查询参数对主要数据进行排序的请求。sort MUST的值表示排序字段。

GET /people?sort=age HTTP/1.1
Accept: application/vnd.api+json

端点可以通过允许逗号分隔(U+002C COMMA, “,”)的排序字段来支持多个排序字段。排序字段应该按指定的顺序应用。

GET /people?sort=age,name HTTP/1.1
Accept: application/vnd.api+json

每个排序字段的排序顺序必须是升序,​​除非它以减号(U+002D HYPHEN-MINUS,“-”)为前缀,在这种情况下它必须降序。

GET /articles?sort=-created,title HTTP/1.1
Accept: application/vnd.api+json

上面的例子应该首先返回最新的文章。在同一日期创建的任何文章将按其标题按字母升序排序。

如果服务器不支持查询参数中指定的排序 sort,它必须返回400 Bad Request

如果服务器支持排序并且客户端通过查询参数请求排序sort,则服务器必须data返回根据指定条件排序的响应的顶级数组的元素 。如果未指定请求参数,服务器可以将默认排序规则应用于顶级。datasort

注意:本节适用于以资源集合作为主要数据进行响应的任何端点,无论请求类型如何。

分页

服务器可以选择限制在响应中返回的资源数量,以响应整个可用集合的子集(“页面”)。

服务器可以提供遍历分页数据集的链接(“分页链接”)。

分页链接必须出现在对应于集合的链接对象中。要对主要数据进行分页,请在顶级links对象中提供分页链接。要对复合文档中返回的包含集合进行分页,请在相应的链接对象中提供分页链接。

以下键必须用于分页链接:

  • first:第一页数据
  • last: 最后一页数据
  • prev: 上一页数据
  • next: 下一页数据

必须要么被省略,要么有一个null值来指示一个特定的链接不可用。

顺序的概念,如分页链接的命名所表达的,必须与 JSON:API 的排序规则 保持一致。

page查询参数保留用于分页。服务器和客户端 应该使用这个键进行分页操作。

注意:JSON:API 与服务器使用的分页策略无关。有效的分页策略包括(但不限于):基于页面、基于偏移量和基于光标。page查询参数可以用作任何这些策略的基础。例如,基于页面的策略可能使用查询参数,例如page[number]and page[size],基于偏移量的策略可能使用page[offset]and page[limit],而基于游标的策略可能使用page[cursor]

注意:上面的示例查询参数使用未编码[]字符只是为了便于阅读。在实践中,这些字符必须按照RFC 3986中的要求进行百分比编码。

注意:本节适用于以资源集合作为主要数据进行响应的任何端点,无论请求类型如何。

过滤

filter查询参数保留用于过滤数据。服务器和客户端 应该使用这个键进行过滤操作。

注意:JSON:API 与服务器支持的策略无关。filter查询参数可以用作任意数量的过滤策略的基础。

创建、更新和删除资源

服务器可以允许创建给定类型的资源。它还可以 允许修改或删除现有资源。

请求必须完全成功或失败(在单个“事务”中)。不允许部分更新。

注意:在 JSON:API 中的请求和响应中type,每个资源对象都需要该成员。在某些情况下,例如当POST访问表示异构数据的端点时,type无法从端点推断出。但是,在需要时进行挑选会令人困惑;很难记住什么时候需要,什么时候不需要。因此,type始终需要提高一致性并最大限度地减少混淆。

创建资源

可以通过向POST代表资源集合的 URL 发送请求来创建资源。请求必须包含一个资源对象 作为主要数据。资源对象 必须至少包含一个成员type

例如,可以使用以下请求创建一张新照片:

POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

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

如果在资源对象relationships的成员中 提供了关系,则其值必须是具有 成员的关系对象。此键的值表示资源将具有的链接。data

客户端生成的 ID

服务器可以接受客户端生成的 ID 以及创建资源的请求。必须使用键指定ID id,其值必须是通用唯一标识符。客户端应该使用RFC 4122 [ RFC4122 ]中描述的正确生成和格式化的UUID 。

注意:在某些用例中,例如从其他来源导入数据,可能会使用除 UUID 之外的其他东西,但仍保证全局唯一。除非您 100% 确信您使用的策略确实会生成全局唯一标识符,否则请勿使用 UUID 以外的任何内容。

例如:

POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": {
    "type": "photos",
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "attributes": {
      "title": "Ember Hamster",
      "src": "http://example.com/images/productivity.png"
    }
  }
}

服务器必须返回403 Forbidden以响应不受支持的请求以创建具有客户端生成 ID 的资源。

回应

201 已创建

如果POST请求不包含客户端生成的 ID并且请求的资源已成功创建,则服务器必须返回201 Created状态代码。

响应应该包含一个Location标头,标识新创建的资源的位置。

响应还必须包含一个包含创建的主要资源的文档。

如果响应返回的资源对象在其成员中包含self键 并且提供了标头,则 成员的值必须与标头的值匹配。linksLocationselfLocation

HTTP/1.1 201 Created
Location: http://example.com/photos/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/vnd.api+json

{
  "data": {
    "type": "photos",
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "attributes": {
      "title": "Ember Hamster",
      "src": "http://example.com/images/productivity.png"
    },
    "links": {
      "self": "http://example.com/photos/550e8400-e29b-41d4-a716-446655440000"
    }
  }
}

202 接受

如果创建资源的请求已被接受处理,但在服务器响应时处理尚未完成,则服务器必须返回202 Accepted状态码。

204 无内容

如果POST请求确实包含客户端生成的 ID并且请求的资源已成功创建,则服务器必须返回201 Created状态代码和响应文档(如上所述)或204 No Content没有响应文档的状态代码。

注意:如果收到响应,客户端应该认为请求中发送的资源对象被服务器接受,就好像服务器在响应204中返回了它一样。201

403 禁止

服务器可以返回403 Forbidden以响应不受支持的创建资源的请求。

404 未找到

当处理引用不存在的相关资源的请求时,服务器必须返回。404 Not Found

409 冲突

当处理请求以创建具有已存在的客户端生成 ID 的资源时,服务器必须返回。409 ConflictPOST

当处理资源对象不在构成端点表示的集合的类型中的请求时,服务器必须返回。409 ConflictPOSTtype

服务器应该包含错误细节并提供足够的信息来识别冲突的来源。

其他回应

服务器可以使用其他 HTTP 状态代码进行响应。

服务器可以包含带有错误响应的错误详细信息。

服务器必须准备响应,客户端必须根据 HTTP semantics.

更新资源

可以通过向代表资源的 URL 发送PATCH请求来更新资源。

资源的 URL 可以在self资源对象的链接中获得。或者,当GET请求返回单个资源对象作为主要数据时,可以使用相同的请求 URL 进行更新。

PATCH请求必须包含一个资源对象作为主要数据。资源对象 必须包含typeid成员。

例如:

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

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

更新资源的属性

任何或所有资源的属性都 可以包含在PATCH请求中包含的资源对象中。

如果请求不包括资源的所有属性,则服务器 必须解释丢失的属性,就好像它们包含在它们的当前值中一样。服务器不得将缺失的属性解释为null 值。

例如,以下PATCH请求被解释为仅更新文章的titletext属性的请求:

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

{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "To TDD or Not",
      "text": "TLDR; It's complicated... but check your test coverage regardless."
    }
  }
}

更新资源的关系

任何或所有资源的关系都 可以包含在PATCH请求中包含的资源对象中。

如果请求不包括资源的所有关系,服务器 必须解释丢失的关系,就好像它们包含在它们的当前值中一样。它绝不能将它们解释为null空值。

如果relationships在请求中的资源对象的成员中提供了关系PATCH,则其值必须是具有data成员的关系对象。关系的值将替换为此成员中指定的值。

例如,以下PATCH请求将更新author一篇文章的关系:

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

{
  "data": {
    "type": "articles",
    "id": "1",
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "1" }
      }
    }
  }
}

同样,以下PATCH请求执行tags文章的完全替换:

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

{
  "data": {
    "type": "articles",
    "id": "1",
    "relationships": {
      "tags": {
        "data": [
          { "type": "tags", "id": "2" },
          { "type": "tags", "id": "3" }
        ]
      }
    }
  }
}

服务器可以拒绝完全替换一对多关系的尝试。在这种情况下,服务器必须拒绝整个更新,并返回403 Forbidden响应。

注意:由于完全替换可能是一个非常危险的操作,服务器可能会选择禁止它。例如,如果服务器没有向客户端提供相关对象的完整列表,并且不希望允许删除客户端未看到的记录,则服务器可能会拒绝完全替换。

回应

202 接受

如果更新请求已被接受处理,但在服务器响应时处理尚未完成,则服务器必须 返回202 Accepted状态码。

200 好

如果服务器接受更新但也以请求指定的方式以外的方式更改资源(例如,更新updated-at 属性或计算的sha),它必须返回200 OK响应。响应文档必须包含更新资源的表示,就好像GET对请求 URL 发出请求一样。

如果更新成功,服务器必须返回一个200 OK状态码,客户端的当前字段保持最新,服务器只响应顶级数据。在这种情况下,服务器不得包含更新资源的表示。

204 无内容

如果更新成功并且服务器没有更新除了提供的字段之外的任何字段,则服务器必须返回200 OK状态代码和响应文档(如上所述)或204 No Content没有响应文档的状态代码。

403 禁止

服务器必须返回403 Forbidden以响应不受支持的更新资源或关系的请求。

404 未找到

在处理修改不存在的资源的请求时,服务器必须返回。404 Not Found

当处理引用不存在的相关资源的请求时,服务器必须返回。404 Not Found

409 冲突

如果更新将违反其他服务器强制约束(例如对除 之外的属性的唯一性约束),服务器可能409 Conflict会在处理更新资源的请求时返回。PATCHid

当处理资源对象与服务器端点不匹配的请求时,服务器必须返回。409 ConflictPATCHtypeid

服务器应该包含错误细节并提供足够的信息来识别冲突的来源。

其他回应

服务器可以使用其他 HTTP 状态代码进行响应。

服务器可以包含带有错误响应的错误详细信息。

服务器必须准备响应,客户端必须根据 HTTP semantics.

更新关系

虽然关系可以与资源一起修改(如上所述),但 JSON:API 还支持在来自关系链接的 URL 处独立更新关系。

注意:在不暴露底层服务器语义(例如外键)的情况下更新关系。此外,可以更新关系而不必影响相关资源。例如,如果一篇文章有​​很多作者,则可以从文章中删除其中一位作者而不删除该人本身。同样,如果一篇文章有​​很多标签,则可以添加或删除标签。在服务器的底层,这些示例中的第一个可以用外键实现,而第二个可以用连接表实现,但是 JSON:API 协议在两种情况下都是相同的。

注意:如果删除关系(作为垃圾收集措施),服务器可能会选择删除底层资源。

更新一对一的关系

服务器必须响应PATCH从一对一 关系链接到 URL 的请求,如下所述。

PATCH请求必须包含一个名为的顶级成员data,其中包含以下内容之一:

例如,以下请求更新文章的作者:

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

{
  "data": { "type": "people", "id": "12" }
}

以下请求清除了同一篇文章的作者:

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

{
  "data": null
}

如果关系更新成功,那么服务器必须返回一个成功的响应。

更新多对多关系

服务器必须响应PATCHPOST, 和DELETE来自一对多关系链接的 URL 请求,如下所述。

对于所有请求类型,主体必须包含一个data成员,其值为空数组或资源标识符对象数组。

如果客户端PATCH从一对多 关系链接向 URL 发出请求,服务器必须要么完全替换关系中的每个成员,如果无法找到或访问某些资源,则返回适当的错误响应,或者403 Forbidden 如果完成则返回响应服务器不允许更换。

例如,以下请求替换文章的每个标签:

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

{
  "data": [
    { "type": "tags", "id": "2" },
    { "type": "tags", "id": "3" }
  ]
}

以下请求会清除文章的每个标签:

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

{
  "data": []
}

如果客户端从关系链接POST向 URL 发出请求 ,服务器必须将指定的成员添加到关系中,除非它们已经存在。如果一个给定的 并且已经在关系中,服务器不能再次添加它。typeid

注意:这与使用外键进行多对多关系的数据库的语义相匹配。基于文档的存储应在追加之前检查 has-many 关系以避免重复。

如果所有指定的资源都可以添加到或者已经存在于关系中,那么服务器必须返回一个成功的响应。

注意:如果服务器的状态与请求的状态匹配,此方法可确保请求成功,并有助于避免由多个客户端对关系进行相同更改而导致的无意义的竞争条件。

在下面的示例中,带有 ID 的评论123被添加到带有 ID 的文章的评论列表中1

POST /articles/1/relationships/comments HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": [
    { "type": "comments", "id": "123" }
  ]
}

如果客户端从关系链接DELETE向 URL 发出请求, 服务器必须从关系中删除指定的成员或返回响应。如果所有指定的资源都能够从关系中删除,或者已经从关系中丢失,那么服务器必须返回一个成功的响应。403 Forbidden

注意:正如上POST面对请求的描述,这种方法有助于避免多个客户端之间进行相同更改的无意义的竞争条件。

关系成员的指定方式与POST请求中相同。

在以下示例中,从 ID 为 的文章的评论列表中删除了 ID 为12和的评论:131

DELETE /articles/1/relationships/comments HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": [
    { "type": "comments", "id": "12" },
    { "type": "comments", "id": "13" }
  ]
}

注意:RFC 7231 指定 DELETE 请求可以包含正文,但服务器可以拒绝该请求。该规范定义了服务器的语义,我们正在为 JSON:API 定义它的语义。

回应

202 接受

如果已接受关系更新请求进行处理,但在服务器响应时尚未完成处理,则服务器必须返回202 Accepted状态码。

204 无内容

如果更新成功并且请求中的资源表示与结果匹配,则服务器必须返回状态码。204 No Content

注意:当该关系已经存在时,这是对POST从一对多关系链接发送到 URL的请求的适当响应。当该关系不存在时,它也是对DELETE从一对多关系链接发送到 URL 的请求的适当响应。

200 好

如果服务器接受更新但也以请求指定的方式以外的其他方式更改目标关系,它必须返回200 OK响应。响应文档必须包含更新关系的表示。

如果更新成功,服务器必须返回200 OK状态码,客户端的当前数据保持最新,并且服务器仅响应顶级数据。在这种情况下,服务器不得 包含更新关系的表示。

403 禁止

服务器必须返回403 Forbidden以响应不受支持的更新关系的请求。

其他回应

服务器可以使用其他 HTTP 状态代码进行响应。

服务器可以包含带有错误响应的错误详细信息。

服务器必须准备响应,客户端必须根据 HTTP semantics.

删除资源

可以通过向资源的 URL 发出请求来删除单个资源:DELETE

DELETE /photos/1 HTTP/1.1
Accept: application/vnd.api+json

回应

202 接受

如果删除请求已被接受处理,但在服务器响应时处理尚未完成,则服务器必须 返回202 Accepted状态码。

204 无内容

如果删除请求成功并且没有返回内容,服务器必须返回状态码。204 No Content

200 好

如果删除请求成功并且服务器仅响应顶级数据,则服务器必须返回状态代码。200 OK

404 未找到

如果删除请求由于资源不存在而失败,服务器应该返回一个状态码。404 Not Found

其他回应

服务器可以使用其他 HTTP 状态代码进行响应。

服务器可以包含带有错误响应的错误详细信息。

服务器必须准备响应,客户端必须根据 HTTP semantics.

查询参数

特定于实现的查询参数必须遵守与成员名称相同的约束,另外要求它们必须包含至少一个非 az 字符(U+0061 到 U+007A)。建议使用 U+ 002D HYPHEN-MINUS、“-”、U+005F LOW LINE、“_”或大写字母(例如 camelCasing)。

如果服务器遇到不遵循上述命名约定的查询参数,并且服务器不知道如何将其作为本规范中的查询参数处理,则它必须返回400 Bad Request.

注意:这是为了保留 JSON:API 对标准查询参数进行附加添加而不与现有实现冲突的能力。

错误

处理错误

服务器可以选择在遇到问题时立即停止处理,或者它可以继续处理并遇到多个问题。例如,服务器可能会处理多个属性,然后在单个响应中返回多个验证问题。

当服务器遇到单个请求的多个问题时,在响应中使用最普遍适用的 HTTP 错误代码。例如,400 Bad Request可能适用于多个 4xx 错误或500 Internal Server Error可能适用于多个 5xx 错误。

错误对象

错误对象提供有关执行操作时遇到的问题的附加信息。错误对象必须errors在 JSON:API 文档的顶层作为键控的数组返回。

一个错误对象可能有以下成员:

  • id:此特定问题出现的唯一标识符。
  • links:一个包含以下成员 的链接对象:
    • about:一个链接,该链接指向有关此特定问题发生的更多详细信息。
  • status:适用于此问题的HTTP状态码,以字符串值表示。
  • code:特定于应用程序的错误代码,以字符串值表示。
  • title: 一个简短的、人类可读的问题摘要,不应该随着问题 的发生而改变,除了本地化的目的。
  • detail:针对此问题发生的特定于人类可读的解释。像 一样title,该字段的值可以本地化。
  • source: 包含对错误源的引用的对象,可选地包括以下任何成员:
    • pointer:指向请求文档中关联实体的 JSON 指针 [ RFC6901"/data" ] [例如,用于主要数据对象或"/data/attributes/title"特定属性]。
    • parameter:一个字符串,指示哪个 URI 查询参数导致错误。
  • meta:一个元对象,包含有关错误的非标准元信息。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值