2012-07-02 49 views
13

許多此處有一個友好的開發人員(有人說是宗教)有關從的RESTful API一個GET請求是否應該返回所請求的資源的ID討論。讓我們假設以下GET請求:RESTful GET響應應該返回資源的ID嗎?

http://my.api.com/rest/users/23

這個當前返回:

{"name": "Jim", "age": 40, "favoriteColor": "blue"} 

注意, 「ID」 是從結果集中遺漏。

基本上有4個陣營正在與這個問題作鬥爭。

CAMP#1:當呼叫者發出GET請求時,他們已經知道該ID。因此,結果集應該包含該ID的而不是。如果調用者需要此數據來啓用UI編輯,則調用者需要通過ID 23,可能會手動將成員{「id」:23}添加到JSON。
1號營地的人們也認爲結果集中ID的存在會表明這個值可以被修改,當然這不能。

CAMP#2:沒有ID,JSON結果集不能用於UI形式的編輯/更新操作。相反,AJAX回調機制需要負責傳遞ID字段並將其手動添加到結果集中。這似乎klunky和容易出錯。這些用戶界面人士認爲結果集「感覺」就像缺少應該存在的數據,即ID。

CAMP#3:這些人關心的一致性。如果我們有一個由API返回的用戶對象的集合,這些對象必須包含這個ID。因此,爲了保持一致性,GET的單例版本還應該包含該ID。

CAMP#4:這些人建議用戶的GET請求可以返回包含ID的HyperMedia或SelfLinks形式的元數據。

這不是一個深奧的「誰是對的?」論點,無論。我們採取的方法將決定我們的API的形狀,並影響幾個開發人員在新的幾周內的工作負載。

+1

這只是個人意見,但我同意第2和第3陣營。我認爲該表示應包含所有可用數據,包括ID。特別是當它是一個自然的ID。這是一個非常有趣的問題,但我懷疑你會找到一個簡單的答案。 – toniedzwiedz

+2

從客戶的角度來看,GET *中使用的URI是ID。我會爲Camp 4投票,假設自我鏈接中使用的「ID」是整個URI,而不僅僅是最後的部分。 –

+0

4號營的人會放心,看到他們並不孤單。並且要確認,如果他們包含該ID,它將被嵌入完整的URI中。這意味着需要解析URI來提取ID,但對於Camp 2人員來說,至少他們不必手動輸入JSON負載。另一方面,Camp 1的追隨者認爲這樣的URI只是REST Level 3的部分實現,所以出於這個原因他們不喜歡嵌入SelfLinks。 –

回答

10

這是一個意見問題,它不是Stackoverflow喜歡看到的那種問題。無論如何,我會提供我的。

您正在返回對象或資源狀態的表示形式。該ID是該表示的一部分,因此應該包含在JSON數據包中。它是資源的一個屬性。來電者是否知道該ID與討論沒有特別密切的關係。 1號營地不穩固。

您提出的有關集合的觀點非常相關。對於retrieve-1操作使用一個表示法,並且對retrieve-N操作使用另一個表示法是否有意義?我想不是。

然而,你面臨的問題是更普遍的 - 哪些數據應包含在被轉移到客戶的代表,以及在什麼情況下?在某些情況下,調用者根本不在乎屬性的重要子集。特別是在大量對象被獲取的情況下 - 傳輸數據的成本與基本通信成本相比更大 - 您希望優化返回的內容。

所有足夠成熟的REST協議都有能力對返回的數據進行整形。

舉例來說,看到

  • Facebook的圖形API,http://developers.facebook.com/docs/reference/api/
  • 的StackExchange API 2.0版 - 有一個 「過濾器」 對象,你可以通過精確地塑造獲取返回的內容。
  • CouchDb API - 具有的每個視圖的映射函數,該視圖確定返回哪些數據。它還有一個覆蓋查詢參數include_docs,它指示服務器包含完整對象或僅包含元數據。 (在某些情況下,您可能希望只是數據,而不是實際的數據的數量。)

Facebook允許你明確指定所需的字段。

enter image description here

的stackexchange API是有趣的。他們已經定義了一種全新的對象來支持整形。您可以使用API​​來定義「過濾器」並將其保存在服務器端。然後在查詢中傳遞一個帶有過濾器ID的過濾器參數,返回的對象表示包含過濾器中指定的所有屬性。沒有過濾器,你會得到一個「默認」字段子集。要獲得「所有領域」,您需要定義一個全包式過濾器。

你可以在https://api.stackexchange.com/docs/answers

在行動中看到這個......具體見過濾器規範對話框。

enter image description here


沒有做的事情沒有唯一正確的方法。您需要平衡您所支持的「塑造」功能的複雜性與開發成本以及將使用該API的應用程序的需求。

+0

謝謝你的周到和詳細的迴應。由於您在第一句話中提出的擔憂,我確實認真考慮提出這個問題:「這是一個意見問題,這不是Stackoverflow喜歡看到的那種問題。」作爲可怕的「同伴壓力」徽章的收件人,我非常清楚嚴格意見的問題會發生什麼。然而,在我看來,這個問題在各個陣營之間有很多編程後果,我決定抓住機會。 –

+1

就我而言,我已經完成了讓第一陣營開心的工作。我現在傳遞一系列可用於擴充或補充由基於AJAX的RESTful服務調用返回的數據的鍵/值對。這有效,但它感覺不對。如果我和API的其他用戶確實想要將這些數據作爲GET有效負載響應的一部分,則營地#1中的人員已同意添加ID。 –

+2

讓我問你 - 如果查詢不是「獲取ID = N的人」而是「使用DOCID = Z獲取文檔的作者」,該怎麼辦?如果你按照營地#1的建議,你會得到一個人物,但你不知道那個人的身份。 「1號營」的立場似乎非常狹隘,站不住腳。除了最簡單和不切實際的情況外,沒有任何意義。 – Cheeso

1

老問題,但自從我來到這裏尋找的東西,在這裏它去另一個觀點:

首先,我認爲URL應該是:

http://my.api.com/rest/Users/23

http://my.api.com/rest/getUsers/23

「GET」取決於HTTP方法,而不是URL。這只是命名,但有助於使事情更清晰,恕我直言。

如果你想一想,一個資源修改需要在相同的URL發生了PUT

PUT http://my.api.com/rest/Users/23

在這種情況下,客戶需要跟蹤的網址,而不是ID的。資源是否返回ID字段無關緊要。客戶需要保存一份從哪裏獲得的地圖。

如果你試圖把一個resorce不同的URL,說「http://my.api.com/rest/Users/24」,會出現幾種情況:

1)http://my.api.com/rest/Users/24已經存在於服務器上,服務器接受資源作爲更新

2)http://my.api.com/rest/Users/24不存在於服務器上和:

a)所述服務器接受用戶被給unexisting資源(不推薦) b)該服務器接受一個PUT作爲POST提供的ID(24)

在a + b中,服務器將創建一個新資源。

所以:

1)取決於你有多少信任你的客戶,你應該建立一個「簽入/簽出」控制的服務器上,以避免覆蓋一個資源與另一個(是這樣的RESTful ?)

2)您不應該接受客戶創建ID(好的,發佈http://my.api.com/rest/Users/,而不是http://my.api.com/rest/Users/24),並且您不應該接受PUT到不存在的資源。

編輯

所以我相信資源由其URL識別,而不是由ID。換句話說,資源ID是http://my.api.com/rest/Users/23,而不是23.

有意義嗎?

+0

我同意在URI中嵌入「get」是一個錯誤。我會看看我是否可以修改OP。感謝您的反饋。 –

+0

「所以我相信資源是通過它的URL來標識的,而不是通過ID來標識的。」這是答案的核心。你的客戶不應該構造URL,所以除非這個ID用於其他目的,否則你不需要將它包含在響應中。甚至沒有收藏。如果您希望客戶知道在哪裏找到單一資源,請提供一個URL而不是一個ID。參見[HATEOAS](http://en.wikipedia.org/wiki/HATEOAS)。 –

相關問題