GET /orders <---> orders
POST /orders <---> orders.push(data)
GET /orders/1 <---> orders[1]
PUT /orders/1 <---> orders[1] = data
GET /orders/1/lines <---> orders[1].lines
POST /orders/1/lines <---> orders[1].lines.push(data)
Don 't try to make it smarter than it has to be - changing from plural to singluar depending on the count of resources you'目前正在访问可能在美学上令人愉悦,但它在 hierarchical 系统中是有意义的 .
18 回答
我更喜欢使用单数形式来实现简单性和一致性 .
例如,考虑以下网址:
/客户/ 1
我会将客户视为客户收集,但为简单起见,我们会删除收集部分 .
另一个例子:
/设备/ 1
在这种情况下,设备不是正确的复数形式 . 因此,将其视为设备集合并简化集合,使其与客户案例保持一致 .
我的两分钱:花时间从复数变为单数或反之的方法是浪费CPU周期 . 我可能是老派,但在我的时间里,事情被称为相同 . 我如何查找有关人的方法?没有定期表达将涵盖人和人没有不良副作用 .
英语复数可以是非常随意的,它们会不必要地妨碍代码 . 坚持一个命名惯例 . 计算机语言应该是关于数学清晰度的,而不是模仿自然语言 .
使用
/resources
的前提是它代表"all"资源 . 如果您执行GET /resources
,则可能会返回整个集合 . 通过POST到/resources
,您将添加到集合中 .但是,个人资源可在/ resource处获得 . 如果你做
GET /resource
,你可能会出错,因为这个请求没有任何意义,而/resource/123
非常有意义 .使用
/resource
而不是/resources
类似于如果使用文件系统和文件集合时如何执行此操作,/resource
是"directory",其中包含单独的123
,456
文件 .无论哪种方式都是对或错,请选择您最喜欢的方式 .
对我来说最好有一个可以直接映射到代码的模式(易于自动化),主要是因为代码是两端的 .
我也没有看到这样做的重点,我认为这不是最好的URI设计 . 作为RESTful服务的用户,我希望列表资源具有相同的名称,无论我是否访问列表中的列表或特定资源 . 无论是否要使用列表资源或特定资源,都应使用相同的标识符 .
Plural
Simple - 所有网址都以相同的前缀开头
Logical -
orders/
获取订单的索引列表 .Standard - 最广泛采用的标准,其次是绝大多数公共和私人API .
例如:
GET /resources
- 返回资源项列表POST /resources
- 创建一个或多个资源项PUT /resources
- 更新一个或多个资源项PATCH /resources
- 部分更新一个或多个资源项DELETE /resources
- 删除所有资源项对于单个资源项:
GET /resources/:id
- 根据:id
参数返回特定资源项POST /resources/:id
- 创建一个具有指定id的资源项(需要验证)PUT /resources/:id
- 更新特定资源项PATCH /resources/:id
- 部分更新特定资源项DELETE /resources/:id
- 删除特定资源项对于单数的拥护者,用这种方式来思考:你会问某人一个人,并期待一件事,或一件事吗?那么,当您键入
/order
时,为什么期望服务返回一个列表?而最普遍的做法是RESTful apis,其中使用复数,例如
/api/resources/123
,有一个特殊情况,我发现使用比复数名称更恰当/富有表现力的单数名称 . 这是一对一关系的情况 . 特别是如果目标项是值对象(在Domain-driven-design范例中) .让我们假设每个资源都有一对一的
accessLog
,它可以被建模为一个值对象,即不是一个实体,因此没有ID . 它可以表示为/api/resources/123/accessLog
. 通常的动词(POST,PUT,DELETE,GET)将恰当地表达意图以及这种关系确实是一对一的事实 .奇异
Convenience 事物可能有不规则的复数名称 . 有时他们没有 . 但奇异的名字总是在那里 .
例如CustomerAddresses上的CustomerAddress
考虑这个相关资源 .
/order/12/orderdetail/12
比/orders/12/orderdetails/4
更具可读性和逻辑性 .数据库表
资源表示像数据库表这样的实体 . 它应该具有逻辑上的单数名称 . 这是表名的answer .
类映射
课程总是单一的 . ORM工具生成与类名相同的表 . 随着越来越多的工具的使用,奇异的名称正在成为一种标准 .
了解更多关于A REST API Developer's Dilemma的信息
为什么不遵循数据库表名的普遍趋势,通常接受单数形式?在那里,完成了 - 让我们重用 .
Table Naming Dilemma: Singular vs. Plural Names
从API使用者的角度来看, endpoints 应该是可预测的
理想的情况下...
GET /resources
应返回资源列表 .GET /resource
应返回400级状态代码 .GET /resources/id/{resourceId}
应返回包含一个资源的集合 .GET /resource/id/{resourceId}
应该返回一个资源对象 .POST /resources
应批量创建资源 .POST /resource
应该创建一个资源 .PUT /resource
应该更新资源对象 .PATCH /resource
应通过仅发布更改的属性来更新资源 .PATCH /resources
应仅批量更新资源过帐改变的属性 .DELETE /resources
应该删除所有资源;开玩笑:400状态代码DELETE /resource/id/{resourceId}
这种方法最灵活,功能最丰富,但也是最耗时的开发方法 . 所以,如果你赶时间(软件开发总是这样),只需命名你的 endpoints
resource
或复数形式resources
. 我更喜欢单数形式,因为它为您提供了以编程方式进行内省和评估的选项,因为并非所有复数形式都以's'结尾 .说了这么多,无论出于何种原因,最常用的练习开发者选择的是使用复数形式 . 这最终是我选择的路线,如果你看一下流行的apis,如
github
和twitter
,这就是他们所做的 .决定的一些标准可能是:
我的时间限制是什么?
我允许消费者做什么操作?
请求和结果有效负载是什么样的?
我是否希望能够使用反射并在我的代码中解析URI?
所以这取决于你 . 无论你做什么都是一致的 .
令我惊讶的是,很多人都会跳上复数名词 . 在实现单数到多数转换时,您是否正在处理不规则复数名词?你喜欢疼吗?
见http://web2.uvcs.uvic.ca/elc/studyzone/330/grammar/irrplu.htm
有许多类型的不规则复数,但这些是最常见的:
名词类型形成复数示例
结束-fe更改f到v然后添加-s刀刀生活生活妻子妻子结束-f更改f到v然后添加-es half halfves狼狼面包饼结束-o添加-es土 beans 土 beans 番茄番茄火山火山结束用-us改变-us到-i仙人掌cacti nucleus nuclei focus foci以-is为结尾变化-is -es分析分析危机危机论文论文以-on更改-on到-a现象现象标准准则ALL KINDS改变元音或更改单词或添加不同的结束男子男子脚英尺儿童儿童人牙齿鼠标老鼠不变的单数和复数是相同的羊鹿鱼(有时)
使用命名约定,通常可以安全地说“只选择一个并坚持下去”,这是有道理的 .
但是,在向许多人解释REST之后,将 endpoints 表示为 paths on a file system 是最具表现力的方式 .
它是无状态的(文件存在或不存在),分层,简单和熟悉 - 您已经知道如何访问静态文件,无论是本地还是通过http .
在这种情况下,语言规则只能让你达到以下目的:
而我喜欢这样 .
虽然,另一方面 - 它's your directory, you can name it 874154 if that' s你想要什么 . 这不是真正重要的事情 .
重要的是,如果将名为"123"的文件放在名为"resourceS"的目录(导致
/resourceS/123
)下,则不能指望它可以通过/resource/123
访问 .Don 't try to make it smarter than it has to be - changing from plural to singluar depending on the count of resources you'目前正在访问可能在美学上令人愉悦,但它在 hierarchical 系统中是有意义的 .
注意:从技术上讲,你可以制作"symbolic links",这样
/resources/123
也可以通过/resource/123
访问,但前者仍然必须存在!我知道大多数人都在决定是使用复数还是单数 . 这里没有解决的问题是客户需要知道您正在使用哪一个,并且他们总是可能犯错误 . 这是我的建议来自的地方 .
How about both? 就此而言,我的意思是对您的整个API使用单数,然后创建路由以将复数形式的请求转发为单数形式 . 例如:
你得到了照片 . 没有人是错的,只需要很少的努力,而且客户永远都会做对 .
对所有方法使用复数至少在一个方面更实用:如果您使用Postman(或类似工具)开发和测试资源API,则无需编辑URI从GET切换到PUT到POST等时
两种表示都很有用 . 我已经使用单数方便了很长一段时间,变形可能很困难 . 我在开发严格单一的REST API方面的经验,使用 endpoints 的开发人员在结果的形状方面缺乏确定性 . 我现在更喜欢使用最能描述响应形状的术语 .
如果您的所有资源都是顶级资源,那么您可以通过单一表示来逃避 . 避免拐点是一个巨大的胜利 .
如果您正在进行任何类型的深层链接来表示关系的查询,那么可以通过更严格的约定来帮助开发人员编写API .
我的惯例是URI中的每个深度级别都在描述与父资源的交互,而完整的URI应该隐式地描述正在检索的内容 .
假设我们有以下模型 .
如果我需要提供允许客户端获取特定用户的特定朋友的经理的资源,它可能看起来像:
GET /users/{id}/friends/{friendId}/manager
以下是一些例子:
GET /users
- 列出全局用户集合中的用户资源POST /users
- 在全局用户集合中创建新用户GET /users/{id}
- 从全局用户集合中检索特定用户GET /users/{id}/manager
- 获取特定用户的经理GET /users/{id}/friends
- 获取用户的朋友列表GET /users/{id}/friends/{friendId}
- 获取用户的特定朋友LINK /users/{id}/friends
- 向此用户添加好友关联UNLINK /users/{id}/friends
- 从此用户中删除朋友关联注意每个级别如何映射到可以对其执行操作的父级 . 对同一个对象使用不同的父对象是违反直觉的 . 在
GET /resource/123
检索资源并未表明创建新资源应该在POST /resources
完成怎么样:
/resource/
(不是/resource
)/resource/
表示's a folder contains something called 874183 , it'是"resouce"文件夹 .而且我认为数据库表的命名约定是相同的,例如,一个名为“user”的表是一个“用户表”,它包含一个名为“user”的东西 .
对我来说,复数操纵 collection ,而单身操纵该集合中的 item .
Collection 允许方法GET / POST / DELETE
Item 允许方法 GET / PUT / DELETE
例如
POST上 /students 将在学校添加一名新学生 .
删除 /students 将删除学校中的所有学生 .
删除 /student/123 将删除学生123 .
它可能感觉不重要但有些工程师有时会忘记id . 如果路径始终为复数并执行DELETE,则可能会意外擦除数据 . 虽然缺少单数上的id将返回未找到的404路径 .
如果API应该暴露多个学校,那么进一步扩展这个例子
删除 /school/abc/students 将删除学校中的所有学生
abc
.选择正确的单词有时候本身就是一个挑战,但我喜欢为集合保留多元化 . 例如 .
cart_items
或cart/items
感觉很对 . 相反,删除cart
,删除自己的购物车对象而不是购物车中的商品;) .我更喜欢使用复数(
/resources
)和单数(/resource/{id}
),因为我认为它更清楚地区分了处理资源集合和处理单一资源之间的逻辑 .作为一个重要的副作用,它也可以帮助防止有人错误地使用API . 例如,考虑用户通过将Id指定为如下参数来错误地尝试获取资源的情况:
在这种情况下,我们使用复数版本,服务器很可能会忽略Id参数并返回所有资源的列表 . 如果用户不小心,他会认为呼叫成功并使用列表中的第一个资源 .
另一方面,使用单数形式时:
服务器很可能会返回错误,因为没有以正确的方式指定Id,用户必须意识到出了问题 .