如何使用inheritancebuild模RESTful API?

我有一个对象层次结构,我需要通过一个RESTful API公开,我不知道我的URL应该如何结构和他们应该返回。 我找不到任何最佳做法。

假设我有从动物inheritance的狗和猫。 我需要对狗和猫进行CRUD操作; 我也希望能够对动物做一般的操作。

我的第一个想法是做这样的事情:

GET /animals # get all animals POST /animals # create a dog or cat GET /animals/123 # get animal 123 

事情是/动物集合现在是“不一致的”,因为它可以返回并采取不完全相同的结构(狗和猫)的对象。 有一个集合返回具有不同属性的对象是否被认为是“RESTful”?

另一个解决scheme是为每个具体types创build一个URL,如下所示:

 GET /dogs # get all dogs POST /dogs # create a dog GET /dogs/123 # get dog 123 GET /cats # get all cats POST /cats # create a cat GET /cats/123 # get cat 123 

但现在,狗猫之间的关系已经失去了。 如果想要检索所有动物,则必须查询狗和猫的资源。 随着每个新的动物亚型,URL的数量也会增加。

另一个build议是增加第二个解决scheme:

 GET /animals # get common attributes of all animals 

在这种情况下,返回的动物将只包含所有动物共有的属性,降低狗的具体和猫的具体属性。 这允许检索所有的动物,虽然具有较less的细节。 每个返回的对象都可以包含指向详细的具体版本的链接。

任何意见或build议?

我会build议:

  • 每个资源只使用一个URI
  • 仅在属性级别区分动物

将多个URI设置为相同的资源从来不是一个好主意,因为它可能会导致混淆和意想不到的副作用。 鉴于此,您的单个URI应该基于像/animals这样的通用scheme。

通过/animals URI方法已经解决了在“基础”层面处理整个狗和猫集合的下一个挑战。

处理像狗和猫这样的专业types的最后挑战可以通过在媒体types中使用查询参数和识别属性的组合来轻松解决。 例如:

GET /animalsAccept : application/vnd.vet-services.animals+json

 { "animals":[ { "link":"/animals/3424", "type":"dog", "name":"Rex" }, { "link":"/animals/7829", "type":"cat", "name":"Mittens" } ] } 
  • GET /animals – 得到所有的狗和猫,会返回雷克斯和手套
  • GET /animals?type=dog – 得到所有的狗,只会返回雷克斯
  • GET /animals?type=cat – 得到所有的猫,只会连指手套

然后当创build或修改动物时,呼叫者有义务指定所涉及的动物types:

媒体types: application/vnd.vet-services.animal+json

 { "type":"dog", "name":"Fido" } 

上述有效负载可以通过POSTPUT请求发送。

上述scheme为您提供了与通过REST进行OOinheritance的基本相似的特性,并且能够在不进行大手术或对URIscheme进行任何更改的情况下添加更多的特化(即更多的动物types)。

我会去/动物返回一个狗和鱼的名单,还有什么其他的:

 <animals> <animal type="dog"> <name>Fido</name> <fur-color>White</fur-color> </animal> <animal type="fish"> <name>Wanda</name> <water-type>Salt</water-type> </animal> </animals> 

应该很容易实现一个类似的JSON例子。

客户总是可以依靠在那里的“名称”元素(一个共同的属性)。 但取决于“types”属性,还有其他元素作为动物表示的一部分。

在返回这样一个列表时,没有任何固有的RESTful或不可靠的 – REST没有规定任何特定的表示数据的格式。 它所说的是数据必须具有一些表示forms,并且该表示forms由媒体types(在HTTP中是Content-Type标题)来标识。

想想你的用例 – 你需要显示一个混合动物列表? 那么,返回一个混合动物数据列表。 你只需要一个狗的名单? 那么,做一个这样的清单。

无论你做/动物?types=狗或/狗是不相关的REST没有规定任何URL格式 – 留在REST范围以外的实施细节。 REST只声明资源应该有标识符 – 不用介意什么格式。

您应该添加一些超媒体链接以更接近RESTful API。 例如通过添加对动物细节的引用:

 <animals> <animal type="dog" href="/animals/123"> <name>Fido</name> <fur-color>White</fur-color> </animal> <animal type="fish" href="/animals/321"> <name>Wanda</name> <water-type>Salt</water-type> </animal> </animals> 

通过添加超级媒体链接,可以减less客户端/服务器之间的耦合 – 在上述情况下,您可以将URL构造的负担从客户端中分离出来,并让服务器决定如何构buildURL(根据定义,它是唯一的权限)。

但现在,狗猫之间的关系已经失去了。

的确,但请记住,URI根本不会反映对象之间的关系。