一些基于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命名约定有点困惑。我们应该用复数还是单数来创建资源?决定的标准应该是什么?
当前回答
以下是Roy Fielding关于“基于网络的软件架构的架构风格和设计”的论文,这句话你可能会感兴趣:
资源是概念上的映射 到一组实体,而不是与中任何特定点的映射对应的实体 时间。
作为一个资源,映射到一组实体,对我来说,使用/product/作为访问一组产品的资源,而不是/products/本身,似乎不符合逻辑。如果需要特定的产品,则访问/products/1/。
作为进一步的参考,这个来源有一些关于资源命名约定的单词和例子:
https://restfulapi.net/resource-naming/
其他回答
我很惊讶地看到这么多人会追随复数名词的潮流。在实现单数到复数的转换时,是否注意到不规则复数名词?你喜欢疼痛吗?
看到 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)
我不喜欢看到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的用户不与(潜在的未来)子资源名重叠。
以下是Roy Fielding关于“基于网络的软件架构的架构风格和设计”的论文,这句话你可能会感兴趣:
资源是概念上的映射 到一组实体,而不是与中任何特定点的映射对应的实体 时间。
作为一个资源,映射到一组实体,对我来说,使用/product/作为访问一组产品的资源,而不是/products/本身,似乎不符合逻辑。如果需要特定的产品,则访问/products/1/。
作为进一步的参考,这个来源有一些关于资源命名约定的单词和例子:
https://restfulapi.net/resource-naming/
使用/resources的前提是它表示“所有”资源。如果执行GET /resources,则可能返回整个集合。通过发布到/resources,您将添加到集合中。
但是,单个资源在/resource上可用。如果执行GET /resource请求,则可能会出错,因为这个请求没有任何意义,而/resource/123则完全有意义。
使用/resource而不是/resources类似于使用文件系统和文件集合,/resource是包含单独的123,456个文件的“目录”。
没有对错之分,你喜欢什么就去做什么。
请参阅谷歌的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 |
|--------------------------+---------------+-------------------+---------------+--------------|
如果你正在思考这个问题,这本书值得一读。