Convention REST URI-nom singulier ou pluriel de la ressource lors de sa création
je suis nouveau au repos et j'ai observé que dans certains services RESTful ils utilisent des URI de ressources différentes pour mettre à jour/obtenir/supprimer et créer. Comme
- Créer - à l'aide de /ressources avec la méthode POST (notez le pluriel) à certains endroits à l'aide de /ressource (au singulier)
- mettre à Jour à l'aide de /ressources/123 avec méthode PUT
- Get - à l'Aide de /ressources/123 avec la méthode GET
je suis un peu confus au sujet de cette convention d'appellation URI. Que devrions-nous utiliser au pluriel ou au singulier pour la création de ressources? Quels devraient être les critères pour décider qui?
18 réponses
la prémisse de l'utilisation de /resources
est qu'il représente" toutes " les ressources. Si vous faites un GET /resources
, vous retournerez probablement toute la collection. En postant à /resources
, vous ajoutez à la collection.
Toutefois, les ressources de l'individu sont disponibles à l' /ressources. Si vous faites un GET /resource
, vous allez probablement faire une erreur, car cette requête n'a aucun sens, alors que /resource/123
a un sens parfait.
à l'Aide de /resource
au lieu de /resources
est similaire à la façon dont vous le feriez si vous travailliez avec, disons, un système de fichiers et un ensemble de fichiers et /resource
est le" répertoire "avec les fichiers individuels 123
, 456
.
ni l'un ni l'autre ne sont bons ou mauvais, aller avec ce que vous aimez le plus.
Pour moi, c'est mieux d'avoir un schéma que vous pouvez mapper directement le code (facile à automatiser), principalement parce que le code est ce qui va être aux deux extrémités.
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)
Je ne vois pas l'intérêt de faire cela non plus et je pense que ce n'est pas le meilleur design URI. En tant qu'utilisateur D'un service RESTful, Je m'attends à ce que la ressource de liste ait le même nom, peu importe si j'accède à la liste ou à la ressource spécifique "dans" la liste. Vous devez utiliser les mêmes identificateurs peu importe si vous voulez utiliser la ressource list ou une ressource spécifique.
pluriel
- Simple - toutes les urls commencent avec le même préfixe
- Logique -
orders/
obtient un indice de la liste des commandes. - Standard - norme la plus largement adoptée, suivie par la majorité écrasante des IPA publics et privés.
pour exemple:
GET /resources
- retourne une liste d'éléments ressources
POST /resources
- crée un ou plusieurs éléments de ressource
PUT /resources
- mise à jour d'une ou de plusieurs ressources
PATCH /resources
- partiellement mises à jour d'un ou de plusieurs ressources
DELETE /resources
- supprime toutes les ressources
et pour des postes distincts:
GET /resources/:id
- renvoie un élément de ressource spécifique basé sur :id
paramètre
POST /resources/:id
- crée un élément de ressource avec un id spécifié (nécessite une validation)
PUT /resources/:id
- mise à jour d'une ressource spécifique
PATCH /resources/:id
- mise à jour partielle d'un élément précis de la ressource
DELETE /resources/:id
- supprime un élément précis de la ressource
aux partisans du singulier, pensez-y de cette façon: demanderiez-vous à quelqu'un un order
et attendez-vous une chose, ou une liste de choses? Alors pourquoi vous attendre à ce qu'un service vous renvoie une liste de choses quand vous tapez /order
?
alors que la pratique la plus répandue est Apis RESTful où les pluriels sont utilisés par exemple /api/resources/123
, il y a un cas spécial où je trouve l'utilisation d'un nom singulier plus approprié/expressif que les noms pluriels. C'est le cas des relations un-à-un. En particulier si l'élément cible est un objet de valeur(dans le paradigme de conception par Domaine).
supposons que chaque ressource a un un-à-un accessLog
qui pourrait être modélisé comme un objet de valeur I. e non une entité donc pas d'identité. Elle pourrait être exprimée comme /api/resources/123/accessLog
. Les verbes habituels (POST, PUT, DELETE, GET) exprimeraient correctement l'intention et aussi le fait que la relation est en effet un à un.
singulier
Commodité Les choses peuvent avoir des noms pluriels irréguliers. Parfois ils n'en ont pas. Mais les noms singuliers sont toujours présents.
p.ex. adresse Client sur Adresse client
tenez compte de cette ressource.
ce /order/12/orderdetail/12
est plus lisible et logique que /orders/12/orderdetails/4
.
Tables De Base De Données
A ressource représente une entité comme une table de base de données. Il doit avoir un nom logique et singulier. Voici la réponse au-dessus des noms de table.
Mapping De La Classe
Les Classessont toujours au singulier. Les outils ORM génèrent des tables avec les mêmes noms que les noms de classe. À mesure que de plus en plus d'outils sont utilisés, les noms singuliers deviennent une norme.
plus d'informations à propos de A REST API Developer's Dilemma
pourquoi ne pas suivre la tendance courante des noms de table de base de données, où un formulaire singulier est généralement accepté? J'y suis allé, j'ai fait ça ... réutilisons.
du point de vue du consommateur de L'IPA, les résultats devraient être prévisibles de sorte que
dans l'idéal...
-
GET /resources
devrait retourner une liste de ressources. -
GET /resource
doit retourner un code de statut de niveau 400. -
GET /resources/id/{resourceId}
doit retourner une collection contenant une ressource. -
GET /resource/id/{resourceId}
doit retourner un objet de ressources. -
POST /resources
devrait créer des ressources par lots. -
POST /resource
devrait créer une ressource. -
PUT /resource
devrait mettre à jour un objet de ressource. -
PATCH /resource
doit mettre à jour une ressource en affichant seulement les attributs modifiés. -
PATCH /resources
doit mettre en lot les ressources de mise à jour en affichant seulement les attributs modifiés. -
DELETE /resources
devrait supprimer toutes les ressources; c'est juste une blague: 400 statut code -
DELETE /resource/id/{resourceId}
cette approche est la plus souple et la plus riche, mais aussi la plus longue à développer. Ainsi, si vous êtes pressé (ce qui est toujours le cas avec le développement de logiciel), il suffit de nommer votre endpoint resource
ou le pluriel resources
. Je préfère la forme singulière parce qu'elle vous donne la possibilité d'introspecter et d'évaluer programmatiquement puisque toutes les formes plurielles se terminent en 's'.
cela dit, quelle que soit la raison pour laquelle les développeurs de pratiques les plus couramment utilisés ont choisi d'utiliser la forme plurielle. C'est finalement la route que j'ai choisie et si vous regardez populaire api comme github
et twitter
, c'est ce qu'ils font.
certains critères de décision pourraient être:
- Quelles sont mes contraintes de temps?
- quelles opérations vais-je permettre à mes consommateurs de faire?
- à quoi ressemble la charge utile request and result?
- est-ce que je veux pouvoir utiliser la réflexion et analyser L'URI dans mon code?
donc c'est à vous de décider. Juste ce que vous ne soyez cohérent.
je suis surpris de voir que tant de gens sauteraient sur le train de noms pluriel. Lors de la mise en œuvre des conversions du singulier au pluriel, prenez-vous soin de noms pluriels irréguliers? Aimez-vous la douleur?
voir http://web2.uvcs.uvic.ca/elc/studyzone/330/grammar/irrplu.htm
il existe de nombreux types de pluriel irrégulier, mais ce sont les plus courants:
Type substantif formant L'exemple du pluriel
se termine par-fe changement f à v puis Ajoutez -s couteau couteaux la vie la vie femme épouses Fin de la phrase-F changer f en v puis Ajoutez -es de la moitié moitiés loup loups pain pains Se termine par-o Add -es de pommes de terre pommes de terre tomate tomates volcan, volcans se termine avec-nous Changer -nous -je cactus cactus noyau noyaux l'accent foyers se termine avec -est le Changement -est -es de l'analyse des analyses la crise des crises thèse de thèses se termine avec -sur Changement-pour -un phénomène phénomène critère critères Toutes sortes de changer la voyelle ou Changer le mot ou Ajouter une fin différente de l'homme des hommes pied pieds enfant les enfants personne, gens dent dents souris souris Immuable au singulier et au pluriel sont les mêmes moutons cerf poisson (parfois)
je préfère utiliser le singulier pour la simplicité et la cohérence.
par exemple, en considérant l'url suivante:
/ client / 1
je traiterai le client comme collection client, mais pour la simplicité, la partie collection est enlevée.
autre exemple:
/équipement/1
dans ce cas, les équipements n'est pas la forme plurielle correcte. Si le traitement qu'il comme une collecte d'équipement et de suppression de collecte pour la simplicité rend compatible avec le cas du client.
mes deux cents: méthodes qui passent leur temps passant du pluriel au singulier ou vice versa sont un gaspillage de cycles CPU. Je suis peut-être de la vieille école, mais à mon époque, c'était pareil. Comment puis-je chercher des méthodes concernant les gens? Aucune expression régulière ne couvrira à la fois la personne et les personnes sans effets secondaires indésirables.
les pluriels anglais peuvent être très arbitraires et ils encombrent inutilement le code. Respectez une convention de nommage. Les langages informatiques ont été c'est censé être une question de clarté mathématique, pas d'imitation du langage naturel.
avec les conventions de nommage, il est généralement sûr de dire "il suffit d'en choisir un et s'y tenir", ce qui a du sens.
cependant, après avoir dû expliquer le repos à beaucoup de gens, représentant des points terminaux comme chemins sur un système de fichiers est la façon la plus expressive de le faire.
Il est apatride (les fichiers existent ou n'existent pas), hiérarchique, simple, et familier - vous savez déjà comment accéder aux fichiers statiques, que ce soit localement ou via http.
et dans ce contexte, les règles linguistiques ne peuvent vous mener que jusqu'à ce qui suit:
un répertoire peut contenir plusieurs fichiers et/ou sous-répertoires, et donc son nom devrait être au pluriel.
et j'aime ça.
Bien que, d'autre part - c'est votre répertoire, vous pouvez le nom de "ressources-ou-plusieurs-ressources" si qu'est ce que vous voulez. Ce n'est pas vraiment la chose la plus importante.
ce qui est important, c'est que si vous placez un fichier nommé" 123 "dans un répertoire nommé" resourceS "(résultant en /resourceS/123
), vous ne pouvez pas vous attendre à ce qu'il soit accessible via /resource/123
.
n'essayez pas de le rendre plus intelligent qu'il ne doit l'être - passer du pluriel au singluar en fonction du nombre de ressources auxquelles vous accédez actuellement peut être agréable sur le plan esthétique pour certains, mais ce n'est pas efficace et n'a pas de sens dans un système hiérarchique .
Note: techniquement, vous pouvez faire des" liens symboliques", de sorte que /resources/123
peut également être accédé via /resource/123
, mais le premier doit encore exister!
je sais que la plupart des gens sont entre la décision d'utiliser le pluriel ou le singulier. Le problème qui n'a pas été abordé ici est que le client aura besoin de savoir lequel vous utilisez, et il est toujours susceptible de faire une erreur. C'est de là que vient ma suggestion.
et les deux? et par cela, je veux dire utiliser le singulier pour toute votre API et ensuite créer des routes pour transmettre les requêtes faites dans la forme plurielle au singulier. Pour exemple:
GET /resources = GET /resource
GET /resources/1 = GET /resource/1
POST /resources/1 = POST /resource/1
...
vous voyez le tableau. Personne n'a tort, effort minimal, et le client aura toujours raison.
utiliser le pluriel pour toutes les méthodes est plus pratique au moins dans un aspect: si vous développez et testez une API ressource en utilisant Postman (ou un outil similaire), vous n'avez pas besoin d'éditer L'URI lorsque vous passez de GET to PUT à POST, etc.
les Deux représentations sont utiles. J'avais utilisé le singulier pour la commodité pendant un certain temps, l'inflexion peut être difficile. Mon expérience dans le développement strictement singulier APIs de repos, les développeurs consommant le point final manque de certitude dans la forme du résultat peut être. Maintenant, je préfère utiliser le terme qui décrit le mieux la forme de la réponse.
si toutes vos ressources sont de niveau supérieur, alors vous pouvez vous en tirer avec des représentations singulières. Éviter l'inflexion est une grande victoire.
si vous faites n'importe quelle sorte de lien profond pour représenter les requêtes sur les relations, alors les développeurs écrivant contre votre API peuvent être aidés en ayant une convention plus stricte.
ma convention est que chaque niveau de profondeur dans une URI décrit une interaction avec la ressource mère, et L'URI complet devrait décrire implicitement ce qui est récupéré.
supposons que nous ayons le modèle suivant.
interface User {
<string>id;
<Friend[]>friends;
<Manager>user;
}
interface Friend {
<string>id;
<User>user;
...<<friendship specific props>>
}
si je devais fournir une ressource qui permet à un client d'obtenir le gestionnaire d'un ami particulier d'un utilisateur particulier, il pourrait ressembler à quelque chose comme:
GET /users/{id}/friends/{friendId}/manager
voici d'autres exemples:
-
GET /users
- liste les ressources de l'utilisateur dans le mondial des utilisateurs de la collection -
POST /users
- créer un nouvel utilisateur dans les utilisateurs mondiaux collection -
GET /users/{id}
- extraire un utilisateur spécifique de la collection global users -
GET /users/{id}/manager
- obtenir le gestionnaire d'un utilisateur spécifique -
GET /users/{id}/friends
- obtenir la liste des amis d'un utilisateur -
GET /users/{id}/friends/{friendId}
- obtenir un ami spécifique d'un utilisateur -
LINK /users/{id}/friends
- ajouter une association d'amis à cet utilisateur -
UNLINK /users/{id}/friends
- supprimer un ami l'association de cet utilisateur
Remarquez comment chaque niveau correspond à un parent qui peuvent être traitées. Utiliser des parents différents pour le même objet est contre-intuitif. Extraire une ressource à GET /resource/123
ne laisse aucune indication que la création d'une nouvelle ressource devrait être faite à POST /resources
Que Diriez-vous de:
/resource/
(pas /resource
)
/resource/
signifie que c'est un dossier contient quelque chose appelé "ressource", c'est une "ressource" du dossier.
et aussi je pense que la convention de nommage des tables de base de données est la même, par exemple, une table appelée 'user' est une" table d'utilisateur", elle contient quelque chose appelé"user".
pour moi , les pluriels manipulent la collection , tandis que les singulaires manipulent le article à l'intérieur de cette collection.
Collection permet les méthodes GET / POST / DELETE
L'article permet les méthodes GET / PUT / DELETE
par exemple
POST on /étudiants va ajouter une nouvelle élève à l'école.
supprimer sur / élèves supprimera tous les élèves de l'école.
supprimer sur / student / 123 supprimera l'étudiant 123 de l'école.
cela peut sembler sans importance, mais certains ingénieurs oublient parfois la carte d'identité. Si la route était toujours au pluriel et a effectué une suppression, vous pourriez accidentellement essuyer vos données. Alors que l'absence de l'id sur le singulier retournera un itinéraire 404 non trouvé.
pour étendre l'exemple si L'API était censée exposer plusieurs écoles, alors quelque chose comme
SUPPRIMER sur /école/abc/étudiants va supprimer tous les élèves de l'école abc
.
choisir le bon mot est parfois un défi en soi, mais j'aime maintenir la pluralité pour la collection. Par exemple: cart_items
ou cart/items
semble juste. En revanche supprimer cart
, supprime l'objet de panier lui-même et non les articles dans le panier ;).
je préfère utiliser à la fois le pluriel ( /resources
) et le singulier ( /resource/{id}
) parce que je pense qu'il sépare plus clairement la logique entre travailler sur la collecte des ressources et travailler sur une seule ressource.
comme un effet secondaire important de cela, il peut également aider à empêcher quelqu'un d'utiliser l'API à tort. Par exemple, considérons le cas où un utilisateur à tort essaie d'avoir une ressource en spécifiant l'Id en paramètre, comme ceci:
GET /resources?Id=123
dans ce cas, lorsque nous utilisons la version plurielle, le serveur ignorera très probablement le paramètre Id et retournera la liste de toutes les ressources. Si l'utilisateur n'est pas prudent, il pensera que l'appel a été un succès et utiliser la première ressource dans la liste.
par contre, en utilisant le singulier:
GET /resource?Id=123
le serveur retournera très probablement une erreur parce que L'Id n'est pas spécifié de la bonne manière, et le l'utilisateur aura à réaliser que quelque chose est faux.