REST URI convention - Singular or plural name of r

2019-01-15 23:33发布

问题:

I'm new to REST and I've observed that in some RESTful services they use different resource URI for update/get/delete and Create. Such as

  • Create - using /resources with POST method (observe plural) at some places using /resource (singular)
  • Update - using /resource/123 with PUT method
  • Get - Using /resource/123 with GET method

I'm little bit confused about this URI naming convention. What should we use plural or singular for resource creation? What should be the criteria while deciding that?

回答1:

The premise of using /resources is that it is representing "all" resources. If you do a GET /resources, you will likely return the entire collection. By POSTing to /resources, you are adding to the collection.

However, the individual resources are available at /resource. If you do a GET /resource, you will likely error, as this request doesn't make any sense, whereas /resource/123 makes perfect sense.

Using /resource instead of /resources is similar to how you would do this if you were working with, say, a file system and a collection of files and /resource is the "directory" with the individual 123, 456 files in it.

Neither way is right or wrong, go with what you like best.



回答2:

For me is better to have a schema that you can map directly to code (easy to automate), mainly because code is what is going to be at both ends.

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) 


回答3:

I don't see the point in doing this either and I think it is not the best URI design. As a user of a RESTful service I'd expect the list resource to have the same name no matter whether I access the list or specific resource 'in' the list. You should use the same identifiers no matter whether you want use the list resource or a specific resource.



回答4:

Plural

  • Simple - all urls start with the same prefix
  • Logical - orders/ gets an index list of orders.
  • Standard - Most widely adopted standard followed by the overwhelming majority of public and private APIs.

For example:

GET /resources - returns a list of resource items

POST /resources - creates one or many resource items

PUT /resources - updates one or many resource items

PATCH /resources - partially updates one or many resource items

DELETE /resources - deletes all resource items

And for single resource items:

GET /resources/:id - returns a specific resource item based on :id parameter

POST /resources/:id - creates one resource item with specified id (requires validation)

PUT /resources/:id - updates a specific resource item

PATCH /resources/:id - partially updates a specific resource item

DELETE /resources/:id - deletes a specific resource item

To the advocates of singular, think of it this way: Would you ask a someone for an order and expect one thing, or a list of things? So why would you expect a service to return a list of things when you type /order?



回答5:

Whereas the most prevalent practice are RESTful apis where plurals are used e.g. /api/resources/123 , there is one special case where I find use of a singular name more appropriate/expressive than plural names. It is the case of one-to-one relationships. Specifically if the target item is a value object(in Domain-driven-design paradigm).

Let us assume every resource has a one-to-one accessLog which could be modeled as a value object i.e not an entity therefore no ID. It could be expressed as /api/resources/123/accessLog. The usual verbs (POST, PUT, DELETE, GET) would appropriately express the intent and also the fact that the relationship is indeed one-to-one.



回答6:

Singular

Convenience Things can have irregular plural names. Sometimes they don't have one. But Singular names are always there.

e.g. CustomerAddress over CustomerAddresses

Consider this related resource.

This /order/12/orderdetail/12 is more readable and logical than /orders/12/orderdetails/4 .

Database Tables

A resource represents a entity like a database table. It should have a logical singular name. Here's the answer over table names.

Class Mapping

Classes are always singular. ORM tools generate tables with same names as class names. As more and more tools are being used, singular names are becoming a standard.

Read more about A REST API Developer's Dilemma



回答7:

Why not follow the prevalent trend of database table names, where a singular form is generally accepted? Been there, done that -- let's reuse.

Table Naming Dilemma: Singular vs. Plural Names



回答8:

From the API consumer's perspective, the endpoints should be predictable so

Ideally...

  1. GET /resources should return a list of resources.
  2. GET /resource should return a 400 level status code.
  3. GET /resources/id/{resourceId} should return a collection with one resource.
  4. GET /resource/id/{resourceId} should return a resource object.
  5. POST /resources should batch create resources.
  6. POST /resource should create a resource.
  7. PUT /resource should update a resource object.
  8. PATCH /resource should update a resource by posting only the changed attributes.
  9. PATCH /resources should batch update resources posting only the changed attributes.
  10. DELETE /resources should delete all resources; just kidding: 400 status code
  11. DELETE /resource/id/{resourceId}

This approach is the most flexible and feature rich, but also the most time consuming to develop. So, if you're in a hurry (which is always the case with software development) just name your endpoint resource or the plural form resources. I prefer the singular form because it gives you the option to introspect and evaluate programmatically since not all plural forms end in 's'.

Having said all that, for whatever reason the most commonly used practice developer's have chosen is to use the plural form. This is ultimately the route I have chosen and if you look at popular apis like github and twitter, this is what they do.

Some criteria for deciding could be:

  1. What are my time constraints?
  2. What operations will I allow my consumers to do?
  3. What does the request and result payload look like?
  4. Do I want to be able to use reflection and parse the URI in my code?

So it's up to you. Just whatever you do be consistent.



回答9:

I am surprised to see that so many people would jump on the plural noun bandwagon. When implementing singular to plural conversions, are you taking care of irregular plural nouns? Do you enjoy pain?

See http://web2.uvcs.uvic.ca/elc/studyzone/330/grammar/irrplu.htm

There are many types of irregular plural, but these are the most common:

Noun type Forming the plural Example

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)


回答10:

I prefer using singular form for both simplicity and consistency.

For example, considering the following url:

/customer/1

I will treat customer as customer collection, but for simplicity, the collection part is removed.

Another example:

/equipment/1

In this case, equipments is not the correct plural form. So treating it as a equipment collection and removing collection for simplicity makes it consistent with the customer case.



回答11:

My two cents: methods who spend their time changing from plural to singular or viceversa are a waste of CPU cycles. I may be old-school, but in my time like things were called the same. How do I look up methods concerning people? No regular expresion will cover both person and people without undesirable side effects.

English plurals can be very arbitrary and they encumber the code needlessly. Stick to one naming convention. Computer languages were supposed to be about mathematical clarity, not about mimicking natural language.



回答12:

With naming conventions, it's usually safe to say "just pick one and stick to it", which makes sense.

However, after having to explain REST to lots of people, representing endpoints as paths on a file system is the most expressive way of doing it.
It is stateless (files either exist or don't exist), hierarchical, simple, and familiar - you already knows how to access static files, whether locally or via http.

And within that context, linguistic rules can only get you as far as the following:

A directory can contain multiple files and/or sub-directories, and therefore its name should be in plural form.

And I like that.
Although, on the other hand - it's your directory, you can name it "a-resource-or-multiple-resources" if that's what you want. That's not really the important thing.

What's important is that if you put a file named "123" under a directory named "resourceS" (resulting in /resourceS/123), you cannot then expect it to be accessible via /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're currently accessing may be aesthetically pleasing to some, but it's not effective and it doesn't make sense in a hierarchical system.

Note: Technically, you can make "symbolic links", so that /resources/123 can also be accessed via /resource/123, but the former still has to exist!



回答13:

I know most people are between deciding whether to use plural or singular. The issue that has not been addressed here is that the client will need to know which one you are using, and they are always likely to make a mistake. This is where my suggestion comes from.

How about both? And by that, I mean use singular for your whole API and then create routes to forward requests made in the plural form to the singular form. For example:

GET  /resources     =     GET  /resource
GET  /resources/1   =     GET  /resource/1
POST /resources/1   =     POST /resource/1
...

You get the picture. No one is wrong, minimal effort, and the client will always get it right.



回答14:

Using plural for all methods is more practical at least in one aspect: if you're developing and testing a resource API using Postman (or similar tool), you don't need to edit the URI when switching from GET to PUT to POST etc.



回答15:

Both representations are useful. I had used singular for convenience for quite some time, inflection can be difficult. My experience in developing strictly singular REST APIs, the developers consuming the endpoint lack certainty in what the shape of the result may be. I now prefer to use the term that best describes the shape of the response.

If all of your resources are top level, then you can get away with singular representations. Avoiding inflection is a big win.

If you are doing any sort of deep linking to represent queries on relations, then developers writing against your API can be aided by having a stricter convention.

My convention is that each level of depth in a URI is describing an interaction with the parent resource, and the full URI should implicitly describe what is being retrieved.

Suppose we have the following model.

interface User {
    <string>id;
    <Friend[]>friends;
    <Manager>user;
}

interface Friend {
    <string>id;
    <User>user;
    ...<<friendship specific props>>
}

If I needed to provide a resource that allows a client to get the manager of a particular friend of a particular user, it might look something like:

GET /users/{id}/friends/{friendId}/manager

The following are some more examples:

  • GET /users - list the user resources in the global users collection
  • POST /users - create a new user in the global users collection
  • GET /users/{id} - retrieve a specific user from the global users collection
  • GET /users/{id}/manager - get the manager of a specific user
  • GET /users/{id}/friends - get the list of friends of a user
  • GET /users/{id}/friends/{friendId} - get a specific friend of a user
  • LINK /users/{id}/friends - add a friend association to this user
  • UNLINK /users/{id}/friends - remove a friend association from this user

Notice how each level maps to a parent that can be acted upon. Using different parents for the same object is counterintuitive. Retrieving a resource at GET /resource/123 leaves no indication that creating a new resource should be done at POST /resources



回答16:

How about:

/resource/ (not /resource)

/resource/ means it's a folder contains something called "resource", it's a "resouce" folder.

And also I think the naming convention of database tables is the same, for example, a table called 'user' is a "user table", it contains something called "user".



回答17:

To me plurals manipulate the collection, whereas singulars manipulate the item inside that collection.

Collection allows the methods GET / POST / DELETE

Item allows the methods GET / PUT / DELETE

For example

POST on /students will add a new student in the school.

DELETE on /students will remove all the students in the school.

DELETE on /student/123 will remove student 123 from the school.

It might feel like unimportant but some engineers sometimes forget the id. If the route was always plural and performed a DELETE, you might accidentally wipe your data. Whereas missing the id on the singular will return a 404 route not found.

To further expand the example if the API was supposed to expose multiple schools, then something like

DELETE on /school/abc/students will remove all the students in the school abc.

Choosing the right word sometimes is a challenge on its own, but I like to maintain plurality for the collection. E.g. cart_items or cart/items feels right. In contrast deleting cart, deletes the cart object it self and not the items within the cart ;).



回答18:

I prefer to use both plural (/resources) and singular (/resource/{id}) because I think that it more clearly separates the logic between working on the collection of resources and working on a single resource.

As an important side-effect of this, it can also help to prevent somebody using the API wrongly. For example, consider the case where a user wrongly tries to get a resource by specifying the Id as a parameter like this:

GET /resources?Id=123

In this case, where we use the plural version, the server will most likely ignore the Id parameter and return the list of all resources. If the user is not careful, he will think that the call was successful and use the first resource in the list.

On the other hand, when using the singular form:

GET /resource?Id=123

the server will most likely return an error because the Id is not specified in the right way, and the user will have to realize that something is wrong.