一些基于rest的服务使用不同的资源uri进行更新/获取/删除和创建。如
Create -在某些地方使用/resource(单数)使用POST方法使用/resources(复数) 更新-使用PUT方法使用/resource/123 Get -使用Get方法使用/resource/123
我对这个URI命名约定有点困惑。我们应该用复数还是单数来创建资源?决定的标准应该是什么?
一些基于rest的服务使用不同的资源uri进行更新/获取/删除和创建。如
Create -在某些地方使用/resource(单数)使用POST方法使用/resources(复数) 更新-使用PUT方法使用/resource/123 Get -使用Get方法使用/resource/123
我对这个URI命名约定有点困惑。我们应该用复数还是单数来创建资源?决定的标准应该是什么?
当前回答
最重要的事情
当你在接口和代码中使用复数时,问问你自己,你的约定是如何处理这些词的:
/pants, /eye-glasses——是单数还是复数? /radii -你知道它的唯一路径是/radius还是/radix吗? /index -你知道它的复数路径是/indexes或/indexes或/indexes吗?
理想情况下,约定的规模应该没有不规则性。英语复数就不会这样,因为
它们也有例外,比如某物被称为复数形式,以及 没有简单的算法可以从一个词的单数中得到一个词的复数,从复数中得到一个词的单数,或者判断一个未知名词是单数还是复数。
这也有缺点。我脑海中最突出的是:
The nouns whose singular and plural forms are the same will force your code to handle the case where the "plural" endpoint and the "singular" endpoint have the same path anyway. Your users/developers have to be proficient with English enough to know the correct singulars and plurals for nouns. In an increasingly internationalized world, this can cause non-negligible frustration and overhead. It singlehandedly turns "I know /foo/{{id}}, what's the path to get all foo?" into a natural language problem instead of a "just drop the last path part" problem.
与此同时,一些人类语言甚至没有名词的单数形式和复数形式。他们还行。你的API也可以。
其他回答
我很惊讶地看到这么多人会追随复数名词的潮流。在实现单数到复数的转换时,是否注意到不规则复数名词?你喜欢疼痛吗?
看到 http://web2.uvcs.uvic.ca/elc/studyzone/330/grammar/irrplu.htm
不规则复数有很多种,但以下是最常见的:
形成复数形式的
Ends with -fe Change f to v then Add -s
knife knives
life lives
wife wives
Ends with -f Change f to v then Add -es
half halves
wolf wolves
loaf loaves
Ends with -o Add -es
potato potatoes
tomato tomatoes
volcano volcanoes
Ends with -us Change -us to -i
cactus cacti
nucleus nuclei
focus foci
Ends with -is Change -is to -es
analysis analyses
crisis crises
thesis theses
Ends with -on Change -on to -a
phenomenon phenomena
criterion criteria
ALL KINDS Change the vowel or Change the word or Add a different ending
man men
foot feet
child children
person people
tooth teeth
mouse mice
Unchanging Singular and plural are the same
sheep deer fish (sometimes)
对我来说,复数操作集合,而单数操作集合中的项。
集合允许使用GET / POST / DELETE方法
项允许GET / PUT / DELETE方法
例如
POST on /students将在学校增加一名新学生。
DELETE on /students将删除学校中的所有学生。
DELETE /student/123将从学校删除学生123。
这可能感觉不重要,但一些工程师有时会忘记id。如果路由总是复数并执行DELETE,可能会意外擦除数据。而在奇异点上缺少id则会返回404路由。
为了进一步扩展示例,如果API应该公开多所学校,那么如下所示
DELETE on /school/abc/students将删除学校abc中的所有学生。
选择正确的词语有时本身就是一个挑战,但我喜欢保持语汇的多样性。例如cart_items或cart/items感觉正确。相反,删除购物车,删除的是购物车对象本身,而不是购物车中的物品;)。
尽管最流行的做法是使用复数的RESTful api,例如/api/resources/123,但有一个特殊的情况,我发现使用单数名称比使用复数名称更合适/更具表现力。这是一对一关系的例子。特别是如果目标项是一个值对象(在领域驱动设计范例中)。
让我们假设每个资源都有一个一对一的accessLog,它可以被建模为一个值对象,即不是实体,因此没有ID。它可以表示为/api/resources/123/accessLog。通常的动词(POST、PUT、DELETE、GET)可以恰当地表达意图,以及关系确实是一对一的事实。
请参阅谷歌的API设计指南:资源名称以了解另一种命名资源的方法。
该指南要求集合以复数形式命名。
|--------------------------+---------------+-------------------+---------------+--------------|
| API Service Name | Collection ID | Resource ID | Collection ID | Resource ID |
|--------------------------+---------------+-------------------+---------------+--------------|
| //mail.googleapis.com | /users | /name@example.com | /settings | /customFrom |
| //storage.googleapis.com | /buckets | /bucket-id | /objects | /object-id |
|--------------------------+---------------+-------------------+---------------+--------------|
如果你正在思考这个问题,这本书值得一读。
我不喜欢看到url的{id}部分与子资源重叠,因为id理论上可以是任何东西,而且会有歧义。它混合了不同的概念(标识符和子资源名)。
类似的问题经常出现在枚举常量或文件夹结构中,其中混合了不同的概念(例如,当您有Tigers、Lions和Cheetahs文件夹时,在同一级别上还有一个名为Animals的文件夹——这没有意义,因为其中一个是另一个的子集)。
一般来说,我认为端点的最后一个命名部分如果一次处理单个实体,应该是单数,如果处理一组实体,则应该是复数。
处理单个用户的端点:
GET /user -> Not allowed, 400
GET /user/{id} -> Returns user with given id
POST /user -> Creates a new user
PUT /user/{id} -> Updates user with given id
DELETE /user/{id} -> Deletes user with given id
然后有一个单独的资源用于对用户进行查询,通常返回一个列表:
GET /users -> Lists all users, optionally filtered by way of parameters
GET /users/new?since=x -> Gets all users that are new since a specific time
GET /users/top?max=x -> Gets top X active users
下面是一些处理特定用户的子资源的例子:
GET /user/{id}/friends -> Returns a list of friends of given user
交个朋友(多对多链接):
PUT /user/{id}/friend/{id} -> Befriends two users
DELETE /user/{id}/friend/{id} -> Unfriends two users
GET /user/{id}/friend/{id} -> Gets status of friendship between two users
永远不会有任何歧义,资源的复数或单数命名都是在暗示用户他们可以期待什么(列表或对象)。对id没有限制,理论上可以让id为new的用户不与(潜在的未来)子资源名重叠。