這一章節(jié)描述JSON API文檔結(jié)構(gòu),通過(guò)媒體類型application/vnd.api+json標(biāo)示。JSON API文檔使用javascript 對(duì)象(JSON)[RFC4627]定義。
盡管同種媒體類型用以請(qǐng)求和響應(yīng)文檔,但某些特性只適用于其中一種。差異在下面呈現(xiàn)。
JSON 對(duì)象必須位于每個(gè)JSON API文檔的根級(jí)。這個(gè)對(duì)象定義文檔的“top level”。
文檔的top level必須包含請(qǐng)求資源或者請(qǐng)求資源集合的實(shí)例 (即主要資源)。
主要資源應(yīng)該以資源類型或者通用鍵"data"索引.
"meta": 資源的元信息,比如分頁(yè)."links": 擴(kuò)展資源關(guān)聯(lián)URLs的URL模板."linked": 資源對(duì)象集合,按照類型分組,鏈接到主要資源或彼此(即鏈接資源)這一章節(jié)描述JSON API文檔如何表示資源。適用于主要資源和鏈接資源。
個(gè)體資源使用單一“資源對(duì)象”(如下描述)或者包含資源ID(如下描述)的字符串表示。
The following post is represented as a resource object: 下面的post表示一個(gè)資源對(duì)象:
{
"posts": {
"id": "1",
// ... attributes of this post
}
}
這個(gè)post用ID簡(jiǎn)單地表示:
{
"posts": "1"
}
任意數(shù)量資源的集合應(yīng)該使用資源對(duì)象數(shù)組,或者IDs數(shù)組,或者一個(gè)簡(jiǎn)單的”集合對(duì)象“表示。
下面這個(gè)post使用資源對(duì)象數(shù)組表示:
{
"posts": [{
"id": "1"
// ... attributes of this post
}, {
"id": "2"
// ... attributes of this post
}]
}
這個(gè)posts使用IDs數(shù)組表示:
{
"posts": ["1", "2"]
}
這些comments使用單一集合對(duì)象表示:
{
"comments": {
"href": "http://example.com/comments/5,12,17,20",
"ids": [ "5", "12", "17", "20" ],
"type": "comments"
}
}
多個(gè)資源對(duì)象有相同的內(nèi)部結(jié)構(gòu),不管他們表示主要資源還是鏈接資源。
下面是一個(gè)可能出現(xiàn)在文檔中的post(即”posts"類型的一個(gè)資源):
{
"posts": {
"id": "1",
"title": "Rails is Omakase"
}
}
在上面這個(gè)例子中,post的資源對(duì)象比較簡(jiǎn)單:
//...
{
"id": "1",
"title": "Rails is Omakase"
}
//...
這一章節(jié)專注于資源對(duì)象,在完整JSON API文檔上下文環(huán)境之外。
資源對(duì)象有四個(gè)保留字:
"id""type""href""links"資源對(duì)象中的其它鍵表示一個(gè)“屬性”。一個(gè)屬性值可以是任何JSON值。
Each resource object SHOULD contain a unique identifier, or ID, when
available. IDs MAY be assigned by the server or by the client, as described
below, and SHOULD be unique for a resource when scoped by its type. An ID
SHOULD be represented by an "id" key and its value MUST be a string
which SHOULD only contain alphanumeric characters, dashes and underscores.
每一個(gè)資源對(duì)象應(yīng)該有一個(gè)唯一標(biāo)示符,或者ID。如下所示,IDs可由服務(wù)器或者客戶端指定,and SHOULD be unique for a resource when scoped by its type. ID應(yīng)該使用 "id"鍵表示,值必須是字符串,且只包含字母,數(shù)字,連字符和下劃線。
URL 模板可以使用IDs來(lái)獲取關(guān)聯(lián)資源,如下所示。
在特殊場(chǎng)景下,客戶端與服務(wù)器之間的唯一標(biāo)識(shí)符信息非必要,JSON API允許缺省IDs。
每個(gè)資源對(duì)象的類型通常由它所在的上下文環(huán)境決定。如上面討論,資源對(duì)象在文檔中通過(guò)類型索引。
每一個(gè)資源對(duì)象可能包含 "type" 鍵來(lái)顯示指定類型。
當(dāng)資源的類型在文檔中未聲明時(shí),"type"鍵不可缺省。
每一個(gè)資源的URL可能使用"href"鍵聲明。資源URLs應(yīng)該由服務(wù)器指定,因此通常包含在響應(yīng)文檔中。
//...
[{
"id": "1",
"href": "http://example.com/comments/1",
"body": "Mmmmmakase"
}, {
"id": "2",
"href": "http://example.com/comments/2",
"body": "I prefer unagi"
}]
//...
服務(wù)器對(duì)特定URLGET請(qǐng)求,響應(yīng)內(nèi)容必須包含資源。
通常在響應(yīng)文檔的根層級(jí)聲明URL 模板會(huì)更高效,而不是在每一個(gè)資源對(duì)象內(nèi)聲明獨(dú)立的URLs。
"links"鍵的值是一個(gè)表示鏈接資源的JSON對(duì)象,通過(guò)關(guān)聯(lián)名索引。
舉例來(lái)說(shuō),下面的post與一個(gè)author和一個(gè)comments集合相關(guān)聯(lián):
//...
{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": "9",
"comments": [ "5", "12", "17", "20" ]
}
}
//...
單對(duì)象關(guān)聯(lián)必須使用上面所述單資源形式的一種來(lái)表示。
舉例來(lái)說(shuō),下面的post與一個(gè)author相關(guān)聯(lián),通過(guò)ID標(biāo)示:
//...
{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": "17"
}
}
//...
下面是一個(gè)示例,鏈接的author用一個(gè)資源對(duì)象表示:
//...
{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": {
"href": "http://example.com/people/17",
"id": "17",
"type": "people"
}
}
}
//...
空白的單對(duì)象關(guān)聯(lián)應(yīng)該用null值表示。舉例來(lái)說(shuō),下面的post沒(méi)有關(guān)聯(lián)author:
//...
{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": null
}
}
//...
多對(duì)象關(guān)聯(lián)必須使用上述資源集合形式的一種來(lái)表示。
舉例來(lái)說(shuō),下面的post與多個(gè)comments關(guān)聯(lián),通過(guò)IDs標(biāo)示:
//...
{
"id": "1",
"title": "Rails is Omakase",
"links": {
"comments": [ "5", "12", "17", "20" ]
}
}
//...
這是一個(gè)使用集合對(duì)象鏈接的comments數(shù)組:
//...
{
"id": "1",
"title": "Rails is Omakase",
"links": {
"comments": {
"href": "http://example.com/comments/5,12,17,20",
"ids": [ "5", "12", "17", "20" ],
"type": "comments"
}
}
}
//...
空白的多對(duì)象關(guān)聯(lián)應(yīng)該使用空數(shù)組表示。舉例來(lái)說(shuō),下面的post沒(méi)有comments:
//...
{
"id": "1",
"title": "Rails is Omakase",
"links": {
"comments": []
}
}
//...
“集合對(duì)象”包含一個(gè)或多個(gè)元素:
"ids" - 關(guān)聯(lián)資源的IDs數(shù)組。"type" - 資源類型"href" - 關(guān)聯(lián)資源的URL(適用于響應(yīng)文檔)。提供包含href屬性集合對(duì)象的服務(wù)器,必須響應(yīng)特定URL GET 請(qǐng)求,響應(yīng)內(nèi)容包含資源對(duì)象集合的關(guān)聯(lián)資源。
頂層的 "links" 對(duì)象可用來(lái)聲明URL模板,從而依據(jù)資源對(duì)象類型獲取最終URLs。
舉例說(shuō)明:
{
"links": {
"posts.comments": "http://example.com/comments?posts={posts.id}"
},
"posts": [{
"id": "1",
"title": "Rails is Omakase"
}, {
"id": "2",
"title": "The Parley Letter"
}]
}
在這個(gè)示例中,請(qǐng)求http://example.com/comments?posts=1 將會(huì)得到"Rails is Omakase"的comments,請(qǐng)求http://example.com/comments?posts=2 將會(huì)得到 "The Parley Letter"的comments.
下面是另外一個(gè)示例:
{
"links": {
"posts.comments": "http://example.com/comments/{posts.comments}"
},
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"comments": [ "1", "2", "3", "4" ]
}
}]
}
在這個(gè)示例中,處理每個(gè)post"links"區(qū)塊內(nèi)的特定數(shù)組,以擴(kuò)展posts.comments變量。URI模板規(guī)范 [RFC6570]聲明默認(rèn)處理方式,使用%編碼(即encodeURIComponent() javascript原生方法)編碼每一個(gè)元素,然后用逗號(hào)連接。在這個(gè)示例中,請(qǐng)求http://example.com/comments/1,2,3,4 ,將會(huì)獲取一個(gè)comments列表。
頂層 "links"對(duì)象具有以下行為:
"posts.comments"指向每個(gè)"posts"對(duì)象的"comments"關(guān)聯(lián).這是另外一個(gè)使用單對(duì)象關(guān)聯(lián)的示例:
{
"links": {
"posts.author": "http://example.com/people/{posts.author}"
},
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": "12"
}
}, {
"id": "2",
"title": "The Parley Letter",
"links": {
"author": "12"
}
}, {
"id": "3",
"title": "Dependency Injection is Not a Virtue",
"links": {
"author": "12"
}
}]
}
這個(gè)實(shí)例中,三個(gè)posts指向author的URL都為http://example.com/people/12.
頂層URL模板允許指定關(guān)聯(lián)作為IDs,但是不要求客戶端硬編碼來(lái)獲取URLs的信息.
注意:為防止沖突,單獨(dú)資源對(duì)象的links對(duì)象優(yōu)先級(jí)高于頂層的links對(duì)象。
為減少HTTP請(qǐng)求,響應(yīng)需要返回所請(qǐng)求的主要資源,同時(shí)可以選擇性的包含鏈接資源。這樣的響應(yīng)稱作“復(fù)合文檔”。
在復(fù)合文檔中,鏈接資源必須作為資源對(duì)象,包含在文檔頂層"linked"對(duì)象中,依據(jù)類型,組合到不同數(shù)組中。
每個(gè)關(guān)聯(lián)的類型,可以在資源層級(jí),或頂層"links"對(duì)象層級(jí),使用"type"鍵指定。能夠輔助客戶端查詢鏈接資源對(duì)象。
{
"links": {
"posts.author": {
"href": "http://example.com/people/{posts.author}",
"type": "people"
},
"posts.comments": {
"href": "http://example.com/comments/{posts.comments}",
"type": "comments"
}
},
"posts": [{
"id": "1",
"title": "Rails is Omakase",
"links": {
"author": "9",
"comments": [ "1", "2", "3" ]
}}, {
"id": "2",
"title": "The Parley Letter",
"links": {
"author": "9",
"comments": [ "4", "5" ]
}}, {
"id": "1",
"title": "Dependency Injection is Not a Virtue",
"links": {
"author": "9",
"comments": [ "6" ]
}
}],
"linked": {
"people": [{
"id": "9",
"name": "@d2h"
}],
"comments": [{
"id": "1",
"body": "Mmmmmakase"
}, {
"id": "2",
"body": "I prefer unagi"
}, {
"id": "3",
"body": "What's Omakase?"
}, {
"id": "4",
"body": "Parley is a discussion, especially one between enemies"
}, {
"id": "5",
"body": "The parsley letter"
}, {
"id": "6",
"body": "Dependency Injection is Not a Vice"
}]
}
}
這種處理方式,保證隨每個(gè)響應(yīng)返回每個(gè)文檔的單例,即使當(dāng)相同的文檔被多次引用時(shí)(這個(gè)實(shí)例中三個(gè)posts的author)。沿著這種方式,如果主要文檔鏈接到另外的主要或鏈接文檔,在"linked"對(duì)象中也不應(yīng)該重復(fù)。