据我所知,每个单独的资源应该只有一个规范路径。那么在下面的例子中,好的URL模式是什么呢?

以公司的rest表示为例。在这个假设的例子中,每个公司拥有0个或多个部门,每个部门拥有0个或多个员工。

没有关联公司,一个部门就不能存在。

一个员工的存在离不开一个相关的部门。

现在我发现资源模式的自然表示是。

公司的集合-接受新公司的POST。获取整个集合。 /companies/{companyId}单个公司。接受GET, PUT和DELETE /companies/{companyId}/departments接受新项的POST。(在公司内部创建一个部门。) /公司/ {companyId} / {departmentId} / /部门 /公司/ / {departmentId} / {companyId} /部门员工 /公司/ {companyId} /部门/ {departmentId} /员工/ {empId}

考虑到每个部分的限制,我认为这是有意义的,如果嵌套有点深的话。

然而,如果我想列出(GET)所有公司的所有员工,我的困难就来了。

它的资源模式将最紧密地映射到/employees(所有员工的集合)

这是否意味着我应该有/employees/{empId},因为如果是这样,那么就有两个URI来获得相同的资源?

或者可能整个模式应该是扁平的,但这意味着雇员是一个嵌套的顶级对象。

在基本层面/员工/?company={companyId}&department={deptId}返回与嵌套最深的模式完全相同的员工视图。

对于资源属于其他资源,但应该可以单独查询的URL模式,最佳实践是什么?


当前回答

我尝试了两种设计策略——嵌套端点和非嵌套端点。我发现:

if the nested resource has a primary key and you don't have its parent primary key, the nested structure requires you to get it, even though the system doesn't actually require it. nested endpoints typically require redundant endpoints. In other words, you will more often than not, need the additional /employees endpoint so you can get a list of employees across departments. If you have /employees, what exactly does /companies/departments/employees buy you? nesting endpoints don't evolve as nicely. E.g. you might not need to search for employees now but you might later and if you have a nested structure, you have no choice but to add another endpoint. With a non-nested design, you just add more parameters, which is simpler. sometimes a resource could have multiple types of parents. Resulting in multiple endpoints all returning the same resource. redundant endpoints makes the docs harder to write and also makes the api harder to learn.

简而言之,非嵌套设计似乎允许更灵活、更简单的端点模式。

其他回答

我读了上面所有的答案,但似乎他们没有共同的策略。我从Microsoft Documents找到了一篇关于Design API最佳实践的好文章。我认为你应该推荐。

In more complex systems, it can be tempting to provide URIs that enable a client to navigate through several levels of relationships, such as /customers/1/orders/99/products. However, this level of complexity can be difficult to maintain and is inflexible if the relationships between resources change in the future. Instead, try to keep URIs relatively simple. Once an application has a reference to a resource, it should be possible to use this reference to find items related to that resource. The preceding query can be replaced with the URI /customers/1/orders to find all the orders for customer 1, and then /orders/99/products to find the products in this order.

.

提示 避免要求资源uri比 收集/项目/集合。

我不同意这种方式

GET /companies/{companyId}/departments

如果您想获取部门,我认为最好使用/departments资源

GET /departments?companyId=123

我假设你有一个公司表和一个部门表,然后用你所使用的编程语言来映射它们。我还假设部门可以附加到其他实体,而不是公司,因此/departments资源是直接的,将资源映射到表很方便,而且由于可以重用,您不需要那么多端点

GET /departments?companyId=123

例如,任何类型的搜索

GET /departments?name=xxx
GET /departments?companyId=123&name=xxx
etc.

如果要创建一个部门,可以使用

POST /departments

资源,请求体应该包含公司ID(如果部门只能链接到一个公司)。

根据django rest框架文档:

一般来说,我们建议尽可能使用平面样式的API表示,但如果适度使用嵌套URL样式也可以是合理的。

https://www.django-rest-framework.org/api-guide/relations/#example_2

Rails为此提供了一个解决方案:浅嵌套。

我认为这很好,因为当您直接处理已知资源时,不需要使用嵌套路由,正如在这里的其他回答中所讨论的那样。

我已经把我所做的事情从问题转移到更多人可能看到的答案。

我所做的是在嵌套端点上创建端点,用于修改或查询项的规范端点不在嵌套资源上。

在这个例子中(只列出改变资源的端点)

POST /companies/创建一个新公司返回一个到已创建公司的链接。 POST /companies/{companyId}/departments当一个部门被放置时,会创建一个新的部门返回到/departments/{departmentId}的链接 PUT /departments/{departmentId}用于修改部门 POST /departments/{deparmentId}/employees创建一个新的员工,返回到/employees/{employeeId}的链接。

因此,每个集合都有根级资源。但是,create是在所属对象中。