it-swarm.com.de

REST URI-Konvention - Einzel- oder Pluralname der Ressource beim Erstellen

Ich bin neu in REST und habe festgestellt, dass in einigen RESTful-Diensten unterschiedliche Ressourcen-URIs zum Aktualisieren/Abrufen/Löschen und Erstellen verwendet werden

  • Erstellen Sie - mit /resources mit POST Methode (Plural beachten) an einigen Stellen mit /resource (singular)
  • Aktualisieren Sie - unter Verwendung von /resource/123 mit der Methode PUT
  • Holen Sie sich - mit /resource/123 mit der GET-Methode

Ich bin ein bisschen verwirrt über diese URI-Namenskonvention. Was sollten wir für die Erstellung von Ressourcen im Plural oder Singular verwenden? Nach welchen Kriterien soll das entschieden werden?

464
JPReddy

Die Voraussetzung für die Verwendung von /resources ist, dass es "alle" Ressourcen darstellt. Wenn Sie ein GET /resources, werden Sie wahrscheinlich die gesamte Sammlung zurückgeben. Durch POST an /resources, fügen Sie der Sammlung hinzu.

Die einzelnen Ressourcen sind jedoch unter/resource verfügbar. Wenn Sie ein GET /resource, Sie werden wahrscheinlich einen Fehler machen, da diese Anfrage keinen Sinn ergibt, während /resource/123 Macht perfekt Sinn.

Mit /resource anstatt /resources ähnelt der Vorgehensweise, wenn Sie beispielsweise mit einem Dateisystem und einer Sammlung von Dateien arbeiten und /resource ist das "Verzeichnis" mit dem individuellen 123, 456 Dateien darin.

Kein Weg ist richtig oder falsch, gehen Sie mit, was Sie am besten mögen.

248
Will Hartung

Für mich ist es besser, ein Schema zu haben, das Sie direkt dem Code zuordnen können (leicht zu automatisieren), hauptsächlich weil Code an beiden Enden sein wird.

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) 
547
jla

Ich sehe auch keinen Grund, dies zu tun, und ich denke, es ist nicht das beste URI-Design. Als Benutzer eines RESTful-Dienstes würde ich erwarten, dass die Listenressource den gleichen Namen hat, unabhängig davon, ob ich auf die Liste oder auf eine bestimmte Ressource in der Liste zugreife. Sie sollten dieselben Bezeichner verwenden, unabhängig davon, ob Sie die Listenressource oder eine bestimmte Ressource verwenden möchten.

257
Jan Deinhard

Plural

  • Einfach - Alle URLs beginnen mit dem gleichen Präfix
  • Logisch - orders/ Erhält eine Indexliste der Bestellungen.
  • Standard - Am weitesten verbreiteter Standard, gefolgt von der überwiegenden Mehrheit der öffentlichen und privaten APIs.

Zum Beispiel:

GET /resources - Gibt eine Liste der Ressourcenelemente zurück

POST /resources - Erstellt einen oder mehrere Ressourceneinträge

PUT /resources - Aktualisiert einen oder mehrere Ressourceneinträge

PATCH /resources - Aktualisiert einen oder mehrere Ressourceneinträge teilweise

DELETE /resources - löscht alle Ressourcenelemente

Und für einzelne Ressourcenelemente:

GET /resources/:id - Gibt ein bestimmtes Ressourcenelement basierend auf dem Parameter :id Zurück

POST /resources/:id - Erstellt ein Ressourcenelement mit der angegebenen ID (erfordert eine Validierung)

PUT /resources/:id - Aktualisiert ein bestimmtes Ressourcenelement

PATCH /resources/:id - Aktualisiert einen bestimmten Ressourceneintrag teilweise

DELETE /resources/:id - löscht einen bestimmten Ressourceneintrag

Denken Sie an die Verfechter von Singular so: Würden Sie jemanden um ein order bitten und eine Sache oder eine Liste von Dingen erwarten? Warum sollten Sie also erwarten, dass ein Service eine Liste von Dingen zurückgibt, wenn Sie /order Eingeben?

61
Eric Knudtson

Singular

Bequemlichkeit Dinge können unregelmäßige Pluralnamen haben. Manchmal haben sie keine. Aber Singularnamen sind immer da.

z.B. Kundenadresse über Kundenadressen

Betrachten Sie diese verwandte Ressource.

Diese /order/12/orderdetail/12 ist lesbarer und logischer als /orders/12/orderdetails/4.

Datenbanktabellen

Eine Ressource repräsentiert eine Entität wie eine Datenbanktabelle. Es sollte einen logischen singulären Namen haben. Hier ist das Antwort über Tabellennamen.

Klassenzuordnung

Klassen sind immer singulär. ORM-Tools generieren Tabellen mit denselben Namen wie Klassennamen. Da immer mehr Werkzeuge verwendet werden, werden einzelne Namen zum Standard.

Lesen Sie mehr über A REST API Developer's Dilemma

39
Sorter

Während die am weitesten verbreitete Praxis RESTful apis ist, wo Pluralformen verwendet werden, z. /api/resources/123, es gibt einen speziellen Fall, in dem ich die Verwendung eines einzelnen Namens angemessener/aussagekräftiger finde als die Verwendung von Pluralnamen. Es ist der Fall von Eins-zu-Eins-Beziehungen. Insbesondere, wenn das Zielelement ein Wertobjekt ist (im domänengetriebenen Entwurfsparadigma).

Nehmen wir an, jede Ressource hat eine Eins-zu-Eins-Beziehung accessLog, die als Wertobjekt modelliert werden könnte, d. H. Keine Entität, daher keine ID. Es könnte ausgedrückt werden als /api/resources/123/accessLog. Die üblichen Verben (POST, PUT, DELETE, GET) würden die Absicht und auch die Tatsache angemessen ausdrücken, dass die Beziehung tatsächlich eins zu eins ist.

29
redzedi

Warum nicht dem vorherrschenden Trend von Datenbanktabellennamen folgen, bei denen eine singuläre Form allgemein akzeptiert wird? War schon da, mach das - lass uns wiederverwenden.

Tabellennamensdilemma: Singular vs. Plural Names

20
Slawomir

Ich bin überrascht zu sehen, dass so viele Menschen auf das Nomen „Zug um Zug“ springen würden. Kümmern Sie sich bei der Implementierung von Konvertierungen von Singular in Plural um unregelmäßige Substantive im Plural? Schmerzt du gern?

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

Es gibt viele Arten von unregelmäßigen Pluralformen, aber diese sind die häufigsten:

Nomenart Bilden des Pluralbeispiels

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)
14

Aus Sicht des API-Verbrauchers sollten die Endpunkte also vorhersehbar sein

Im Idealfall...

  1. GET /resources sollte eine Liste von Ressourcen zurückgeben.
  2. GET /resource sollte einen Statuscode mit 400 Ebenen zurückgeben.
  3. GET /resources/id/{resourceId} sollte eine Sammlung mit einer Ressource zurückgeben.
  4. GET /resource/id/{resourceId} sollte ein Ressourcenobjekt zurückgeben.
  5. POST /resources sollte im Batch Ressourcen erstellen.
  6. POST /resource sollte eine Ressource erstellen.
  7. PUT /resource sollte ein Ressourcenobjekt aktualisieren.
  8. PATCH /resource sollte eine Ressource aktualisieren, indem nur die geänderten Attribute veröffentlicht werden.
  9. PATCH /resources sollte die Ressourcen stapelweise aktualisieren und nur die geänderten Attribute veröffentlichen.
  10. DELETE /resources sollte alle Ressourcen löschen; nur ein Scherz: 400 Status-Code
  11. DELETE /resource/id/{resourceId}

Dieser Ansatz ist der flexibelste und funktionsreichste, aber auch der zeitaufwendigste für die Entwicklung. Wenn Sie es eilig haben (was bei der Softwareentwicklung immer der Fall ist), nennen Sie einfach Ihren Endpunkt resource oder die Pluralform resources. Ich bevorzuge die Singularform, weil Sie die Möglichkeit haben, programmgesteuert zu prüfen und zu bewerten, da nicht alle Pluralformen mit 's' enden.

Aus welchem ​​Grund auch immer der am häufigsten verwendete Übungsentwickler gewählt hat, ist es dennoch, die Pluralform zu verwenden. Dies ist letztendlich die Route, die ich gewählt habe, und wenn Sie sich beliebte APIs wie github und Twitter ansehen, dann tun sie das auch.

Einige Entscheidungskriterien könnten sein:

  1. Was sind meine zeitlichen Einschränkungen?
  2. Welche Operationen werde ich meinen Verbrauchern erlauben?
  3. Wie sehen die Nutzdaten für Anforderung und Ergebnis aus?
  4. Möchte ich in der Lage sein, Reflection zu verwenden und den URI in meinem Code zu analysieren?

Also liegt es an dir. Was auch immer Sie tun, seien Sie konsequent.

13
cosbor11

Ich bevorzuge die Verwendung der Singularform sowohl aus Gründen der Einfachheit als auch der Konsistenz.

Betrachtet man beispielsweise die folgende URL:

/ Kunde/1

Ich werde den Kunden als Kundenabholung behandeln, aber der Einfachheit halber wird der Abholungsteil entfernt.

Ein anderes Beispiel:

/ ausrüstung/1

In diesem Fall ist Ausrüstungen nicht die richtige Pluralform. Wenn Sie es also als Gerätesammlung behandeln und der Einfachheit halber entfernen, wird es mit dem Kundenfall in Einklang gebracht.

5
ivxivx

Meine zwei Cent: Methoden, die ihre Zeit damit verbringen, von Plural zu Singular oder umgekehrt zu wechseln, sind eine Verschwendung von CPU-Zyklen. Ich mag altmodisch sein, aber zu meiner Zeit hieß es genauso. Wie suche ich nach Methoden, die Menschen betreffen? Keine regelmäßige Expression deckt sowohl Personen als auch Personen ohne unerwünschte Nebenwirkungen ab.

Englische Pluralformen können sehr willkürlich sein und belasten den Code unnötig. Halten Sie sich an eine Namenskonvention. Bei Computersprachen sollte es um mathematische Klarheit gehen, nicht um die Nachahmung der natürlichen Sprache.

5
Guichito

Bei Namenskonventionen ist es normalerweise sicher zu sagen, dass man sich nur an einen hält, was Sinn macht.

Nachdem Sie vielen Leuten REST) erklärt haben, ist die Darstellung von Endpunkten als Pfade in einem Dateisystem die aussagekräftigste Methode, dies zu tun.
Es ist zustandslos (Dateien existieren oder existieren nicht), hierarchisch, einfach und vertraut - Sie wissen bereits, wie Sie auf statische Dateien zugreifen können, ob lokal oder über http.

In diesem Zusammenhang können Sie mit sprachlichen Regeln nur bis zu folgenden Punkten gelangen:

Ein Verzeichnis kann mehrere Dateien und/oder Unterverzeichnisse enthalten. Daher sollte sein Name im Plural sein .

Und ich mag es.
Obwohl es sich auf der anderen Seite um Ihr Verzeichnis handelt, können Sie es "eine Ressource oder mehrere Ressourcen" nennen, wenn Sie dies wünschen. Das ist nicht wirklich wichtig.

Was wichtig ist, ist, dass Sie nicht erwarten können, dass eine Datei mit dem Namen "123" unter einem Verzeichnis mit dem Namen "resourceS" (was zu /resourceS/123 Führt) über /resource/123 Zugänglich ist.

Versuchen Sie nicht, es schlauer zu machen, als es sein muss - abhängig von der Anzahl der Ressourcen, auf die Sie momentan zugreifen, kann es für einige ästhetisch ansprechend sein, aber es ist nicht effektiv und macht in a keinen Sinn hierarchisch System.

Hinweis: Technisch können Sie "symbolische Verknüpfungen" erstellen, so dass /resources/123 Auch über /resource/123 Erreichbar ist, ersteres aber noch vorhanden sein muss!

3
Narf

Eine ID in einer Route sollte genauso angezeigt werden wie ein Index für eine Liste, und die Benennung sollte entsprechend erfolgen.

numbers = [1, 2, 3]

numbers            GET /numbers
numbers[1]         GET /numbers/1
numbers.Push(4)    POST /numbers
numbers[1] = 23    UPDATE /numbers/1

Einige Ressourcen verwenden jedoch keine IDs auf ihren Routen, da entweder nur eine vorhanden ist oder ein Benutzer nie auf mehr als eine zugreifen kann. Dies sind also keine Listen:

GET /dashboard
DELETE /session
POST /login
GET /users/{:id}/profile
UPDATE /users/{:id}/profile
2
TiggerToo

Ich weiß, dass die meisten Menschen sich zwischen Plural und Singular entscheiden. Das Problem, das hier nicht angesprochen wurde, ist, dass der Kunde wissen muss, welchen Sie verwenden, und dass er wahrscheinlich immer einen Fehler macht. Hier kommt mein Vorschlag her.

Wie wäre es mit beiden? Und damit meine ich, dass Sie Singular für Ihre gesamte API verwenden und dann Routen erstellen, um Anforderungen im Plural an die Singular-Form weiterzuleiten. Zum Beispiel:

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

Du bekommst das Bild. Niemand ist falsch, minimaler Aufwand, und der Kunde wird es immer richtig machen.

2
wynnset

Die Verwendung von Plural für alle Methoden ist zumindest unter einem Aspekt praktischer: Wenn Sie eine Ressourcen-API mit Postman (oder einem ähnlichen Tool) entwickeln und testen, müssen Sie den URI beim Wechsel von GET zu PUT zu POST etc.

1
Paulo Merson

Beide Darstellungen sind nützlich. Ich hatte Singular für die Bequemlichkeit für eine ganze Weile verwendet, Beugung kann schwierig sein. Meine Erfahrung in der Entwicklung von streng singulären REST APIs), bei denen die Entwickler, die den Endpunkt verwenden, nicht sicher sind, wie das Ergebnis aussehen soll .

Wenn alle Ihre Ressourcen auf höchstem Niveau sind, können Sie mit singulären Darstellungen davonkommen. Beugung zu vermeiden ist ein großer Gewinn.

Wenn Sie irgendeine Art von Deep-Linking ausführen, um Abfragen zu Relationen darzustellen, können Entwickler, die gegen Ihre API schreiben, durch eine strengere Konvention unterstützt werden.

Meiner Konvention nach beschreibt jede Tiefenebene in einem URI eine Interaktion mit der übergeordneten Ressource, und der vollständige URI sollte implizit beschreiben, was abgerufen wird.

Angenommen, wir haben das folgende Modell.

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

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

Wenn ich eine Ressource bereitstellen müsste, mit der ein Client den Manager eines bestimmten Freundes eines bestimmten Benutzers abrufen kann, könnte dies folgendermaßen aussehen:

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

Im Folgenden sind einige weitere Beispiele aufgeführt:

  • GET /users - listet die Benutzerressourcen in der globalen Benutzersammlung auf
  • POST /users - Erstellt einen neuen Benutzer in der globalen Benutzersammlung
  • GET /users/{id} - Ruft einen bestimmten Benutzer aus der globalen Benutzersammlung ab
  • GET /users/{id}/manager - Ruft den Manager eines bestimmten Benutzers ab
  • GET /users/{id}/friends - Liefert die Freundesliste eines Benutzers
  • GET /users/{id}/friends/{friendId} - Bekomme einen bestimmten Freund eines Benutzers
  • LINK /users/{id}/friends - Füge diesem Benutzer eine Freundschaftsverbindung hinzu
  • UNLINK /users/{id}/friends - entfernt eine Freundschaftsverbindung von diesem Benutzer

Beachten Sie, wie jede Ebene einem übergeordneten Element zugeordnet wird, auf das reagiert werden kann. Die Verwendung verschiedener Eltern für dasselbe Objekt ist nicht intuitiv. Das Abrufen einer Ressource unter GET /resource/123 Gibt keinen Hinweis darauf, dass das Erstellen einer neuen Ressource unter POST /resources Erfolgen sollte.

1
Steve Buzonas

Wie wäre es mit:

/resource/ (nicht /resource)

/resource/ bedeutet, dass es sich um einen Ordner mit dem Namen "resource" handelt, es handelt sich um einen "resouce" -Ordner.

Und ich denke auch, dass die Namenskonvention von Datenbanktabellen dieselbe ist, zum Beispiel ist eine Tabelle mit dem Namen 'user' eine "Benutzertabelle", sie enthält etwas mit dem Namen "user".

0
chrisyue

Checkout Google 's API Design Guide: Ressourcennamen für eine andere Art der Benennung von Ressourcen.

Zusamenfassend:

  • Sammlungen werden mit Plural benannt.
  • Einzelne Ressourcen werden mit einem String benannt.
|--------------------------+---------------+-------------------+---------------+--------------|
| API Service Name         | Collection ID | Resource ID       | Collection ID | Resource ID  |
|--------------------------+---------------+-------------------+---------------+--------------|
| //mail.googleapis.com    | /users        | /[email protected] | /settings     | /customFrom  |
| //storage.googleapis.com | /buckets      | /bucket-id        | /objects      | /object-id   |
|--------------------------+---------------+-------------------+---------------+--------------|
0
Shannon