2017-08-08 21 views
10

我正在嘗試關注JSON API。我需要將CRUD訪問權限暴露給嵌套資源:產品評論。嵌套關係應該反映在JSON API的URL中嗎?

此前使用JSON API,我期望一個REST接口這樣的:

GET /products/:product_id/reviews  - list reviews for a product 
POST /products/:product_id/reviews  - add a review for a product 
PATCH /products/:product_id/reviews/:id - update a review for a product 
DELETE /products/:product_id/reviews/:id - delete a review for a product 

我看到一個嵌套結構的一些提這樣in the spec

例如,URL相片的評論是:

/photos/1/comments

但我不確定這個結構是否適用於所有行爲。

一方面,POST /products/:product_id/reviews創建似乎是多餘的,如果我要在POST主體中指定產品,在審查數據的relationships下。

另一方面,如果刪除評論(可能不是)時指定產品ID很有用,那麼DELETE /products/:product_id/reviews/:id似乎是唯一可行的方法; people argue about whether a request body is even allowed for DELETE requests

我可以巢一些請求,而不是其他:

GET /products/:product_id/reviews - list reviews for a product 
POST /products/:product_id/reviews - add a review for a product 
PATCH /reviews/:id     - update a review 
DELETE /reviews/:id     - delete a review 

但似乎古怪不一致。

我從來沒有窩:

GET /reviews  - list reviews for the product specified in params 
POST /reviews  - add a review for the product specified in params 
PATCH /reviews/:id - update a review 
DELETE /reviews/:id - delete a review 

,但似乎尷尬,似乎並沒有匹配我從文檔所作的第一次報價。

使用JSON API時,嵌套的資源關係應該反映在URL中嗎?

回答

9

我真的很喜歡你的問題,因爲我一直有同樣的想法。我很困惑,沒有人留下答案。

我一直在生產系統上使用JSON API一年多一點,我想給我兩分錢。

起初,當我開始使用JSON API的項目時,我懷疑嵌套資源和非嵌套資源。然後,我遇到了嵌套資源的問題,這些資源在非嵌套資源中可能會被避免。

要採取與您的示例中相同的路徑,請考慮GET /products/:product_id/reviews端點。 當這樣做時,在產品下嵌套評論是非常有意義的,因爲我們最初在產品環境中顯示評論。一切都很好。

然後我們希望在前端構建一個頁面,該頁面顯示用戶以及用戶創作的所有評論。 雖然我們已經有了一個獲得評論的端點,但我們必須建立一個新的評論,例如GET /users/:id/reviews

如果我們把第一個端點放在GET /reviews上,並且過濾器的參數是?filter[product_id]=:id,我們可以在該端點添加一個新的過濾器,這對IMO來說很有意義。

我使用嵌套的資源,但只有像GET /users/:id/email_settings單資源,它是有道理的其他一些特殊情況。

根據我的經驗,如果每個資源被認爲是獨立於其他資源,這使得它在未來更容易。資源之間存在資源和關係。沒有資源在API的上下文中「擁有」另一個資源(在商業邏輯中它是另一個故事)。

我與這個策略奏效了,它仍然讓我驚訝增加新的功能,以現有的端點時,添加新的端點時是否能正常工作。

+2

我也想補充一點,這符合以及對於任何特定資源應該有恰好1個規範URI的想法。使用嵌套資源時,最終可能會有相同資源的許多位置,例如'/ products/1/review/1'和'/ reviews/1'。 重要的區別w.r.t. JSON API是[_relationship_ resources](http://jsonapi.org/format/#fetching-relationships)似乎沒有違反這個想法。它們是兩件事情之間關係___的標準位置,例如'/ products/1/relationships/reviews/1'表示這些資源之間的關聯。 – Iamvery

+1

感謝Lasse和@​​iamvery分享您的見解!這是我最終使用的方法。 –

2

如果從CQRS陣營來了,你就會明白爲什麼設計寧靜的API有時會很尷尬。這很尷尬,因爲自然查詢操作(GET)和突變操作(POST,PATCH,DELETE)應該以兩種不同的語言進行交談。 查詢行爲自然關係導向和數據豐富;而突變行動沒有。因此,使用嵌套URL來遍歷關係實體之間很容易。 但是突變你應該提供足夠的任務信息。有時它像你的Post例子那樣是多餘的。有時會像你的DELETE示例一樣缺失。有時你有一項任務涉及許多資源;你不知道在哪裏放。

您應該檢查的Facebook圖形API或者Azure的圖形API,他們遇到了同樣的問題,並有一些很好的解決方案。重要的是你應該遵循一致的設計。 一些規則是:

  • 刪除,更新始終以直接資源。
  • 嵌套資源使用後,如果你想同時創建對象和主的關係。次要關係應該放在BODY中。如果你有兩個平等的關係,考慮有兩個嵌套的API。
  • 使用POST僞造資源來執行涉及許多資源的任務。

    POST/transferfund

  • 使用POST反對的任務假冒關係可能不適合與任何HTTP動詞。例如,你想有身體刪除操作,使用

    POST /資源/ ID/deleteItForMe {理由: 「我恨它」}