REST-API - Soll die API geschachtelte JSON-Objekte zurückgeben?

37

Wenn es um JSON-APIs geht, ist es empfehlenswert, Antworten zu reduzieren und verschachtelte JSON-Objekte zu vermeiden?

Nehmen wir als Beispiel an, wir haben eine ähnliche API wie IMDb, jedoch für Videospiele. Es gibt ein paar Entitäten, Game, Platform, ESRBRating und GamePlatformMap, die Spiele und Plattformen zuordnen.

Nehmen wir an, Sie fordern / game / 1 an, das das Spiel mit der ID 1 abruft und das Spielobjekt mit den verschachtelten Plattformen und esrbRating zurückgibt.

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": [
    {"id":1,"name":"Xbox"},
    {"id":2,"name":"Playstation"}
  ],
  "esrbRating": {
    "id": 1,
    "code": "E",
    "name": "Everyone"
  }
}

Wenn Sie so etwas wie JPA / Hibernate verwenden, wird dies möglicherweise automatisch für Sie erledigt, wenn FETCH.EAGER eingestellt ist.

Die andere Option besteht darin, einfach die API zu verwenden und weitere Endpunkte hinzuzufügen.

In diesem Fall, wenn / game / 1 angefordert wird, wird nur das Spielobjekt zurückgegeben.

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
}

Wenn Sie die Plattformen und / oder ESRBRating möchten, müssen Sie Folgendes aufrufen:

/ game / 1 / platform / game / 1 / esrb

Diese Methode könnte möglicherweise mehrere weitere Aufrufe an den Server senden, je nachdem, welche Daten der Client benötigt und wann er sie benötigt.

Es gab einen letzten Gedanken, den ich hatte, wo Sie so etwas zurückbekommen würden.

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": ["Xbox","Playstation"]
}

Dies setzt jedoch voraus, dass sie keine IDs oder andere Informationen benötigen, die diesen Plattformobjekten zugeordnet sind.

Ich frage allgemein, wie Sie die von Ihrer API zurückgegebenen JSON-Objekte am besten strukturieren können. Sollten Sie versuchen, so nah wie möglich an Ihren Entitäten zu bleiben, oder ist es in Ordnung, Domänenobjekte oder Datenübertragungsobjekte zu verwenden? Ich verstehe, dass die Methoden Kompromisse haben werden, entweder mehr Arbeit auf der Datenzugriffsebene oder mehr Arbeit für den Client.

Ich würde auch gerne eine Antwort bezüglich der Verwendung von Spring MVC als Back-End-Technologie für die API hören, entweder mit JPA / Hibernate oder MyBatis für die Persistenz.

grauer Fuchs
quelle
6
Welche Einwände haben Sie gegebenenfalls, wenn Sie eingebettete Objekte zurückgeben? Eingebettete Objekte einzeln von verschiedenen Endpunkten zurückzugeben, wird verdammt ärgerlich (ganz zu schweigen von langsam).
Robert Harvey
1
Persönlich habe ich keine Einwände dagegen. Mir ist nur nicht bewusst, was als Best Practices angesehen wird. Ein Kollege behauptet, dass die Arbeit mit eingebetteten Objekten in AngularJS nicht einfach ist und ich möchte, dass die API von der Ember of AngularJS-App verwendet wird. Ich weiß nicht genug über Angular oder Ember, um zu wissen, ob sich das auswirken wird oder nicht.
Greyfox
3
Die Antwort hängt davon ab, ob Sie Domänenobjekte, DTOs, ViewModel-Objekte oder KitchenSink-Objekte zurückgeben möchten. Welches Objekt Sie zurückgeben, hängt sehr wahrscheinlich davon ab, was Ihre Anwendung benötigt und wie sich das Objekt über das Internet verhält. Beispiel: Wenn Sie versuchen, eine Webseite mit Daten aus einer Rechnung zu füllen, wird höchstwahrscheinlich ein Objekt zurückgegeben, das alles enthält, was Sie benötigen (es sei denn, Sie planen AJAXing in den Werbebuchungen oder Ähnliches).
Robert Harvey
In diesem Fall möchten Sie bei der Anforderung eines Spiels wahrscheinlich die Genres, Plattformen und das ESRBRating kennen. Das macht Sinn. Würden Sie in Bezug auf das Design aus Java-Sicht empfehlen, ein Entity-Paket mit JPA-Entitäten und dann ein Domain-Paket zu haben, bei dem die Geschäftsobjekte / DTO an den Benutzer zurückgegeben werden?
Greyfox
1
Anrufe zum Server sind teuer. Eine API, die das Senden von Daten über mehrere Aufrufe erfordert, ist langsamer als eine API, mit der Sie alles in einem Aufruf abrufen können, häufig auch dann, wenn letztere nicht benötigte Informationen zurückgibt.
Gort the Robot

Antworten:

11

Eine weitere Alternative (mit HATEOAS). Dies ist einfach, meistens fügen Sie in der Praxis einen Link-Tag in den JSON ein, abhängig von Ihrer Verwendung von HATEOAS.

http://api.example.com/games/1:

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": [
    {"_self": "http://api.example.com/games/1/platforms/53", "name": "Playstation"},
    {"_self": "http://api.example.com/games/1/platforms/34", "name": "Xbox"},
  ]
}

http://api.example.com/games/1/platforms/34:

{
  "id": 34,
  "title": "Xbox",
  "publisher": "Microsoft",
  "releaseDate": "2015-01-01",
  "testReport": "http://api.example.com/games/1/platforms/34/reports/84848.pdf",
  "forms": [
    {"type": "edit", "fields: [] },
  ]
}

Sie können natürlich alle Daten in alle Auflistungen einbetten, aber das sind wahrscheinlich viel zu viele Daten. Auf diese Weise können Sie die erforderlichen Daten einbetten und dann mehr laden, wenn Sie wirklich damit arbeiten möchten.

Die technische Implementierung kann Caching enthalten. Sie können die Plattformlinks und -namen im Spielobjekt zwischenspeichern und sofort senden, ohne die Plattform-API laden zu müssen. Dann können Sie es bei Bedarf laden.

Sie sehen zum Beispiel, dass ich einige Formularinformationen hinzugefügt habe. Ich habe dies getan, um Ihnen zu zeigen, dass ein detailliertes JSON-Objekt viel mehr Informationen enthalten kann, als Sie in der Liste der Spiele laden möchten.

Luc Franken
quelle
Ich denke nicht, dass das technisch HATEOS ist, da es keinen Staat gibt.
RibaldEddie
Ja, ich bin mir nicht sicher, was genau in diesem Prozess vor sich geht. HATEOS wird im Allgemeinen für die Verlinkung in Rest-APIs verwendet, aber ich bin damit einverstanden, dass es auch mit dem Status zu tun hat. Die Idee der Implementierung wird jedoch dieselbe sein. Hier sehen Sie ein bisschen mehr darüber, wie es von einem Beispiel verwendet werden kann: stormpath.com/blog/linking-and-resource-expansion-rest-api-tips
Luc Franken
Es ist jedoch eine gute Idee!
RibaldEddie
1
Wenn Sie eine API entwickeln, bei der eine Kohäsion zwischen dem Client und der API selbst besteht (z. B. einer internen API), ist es möglicherweise sinnvoller, eine verschachtelte (oder abgeflachte) Antwort zurückzugeben, anstatt Links zu einer anderen Ressource bereitzustellen. Dies bedeutet mehr API-Anforderungen das kann unerwünscht sein.
Bruno
@bruno ja, aber mit Einschränkungen: Auf größeren Systemen können oder wollen Sie nicht alle zugehörigen Objekte vollständig bereitstellen. Die Felder, die Sie standardmäßig einschließen, sind willkürlich. Sie können sie basierend auf der Verwendung Ihrer API auswählen. In diesem Fall haben Sie möglicherweise Plattformen mit Hunderten von Feldern. Im Anwendungsfall wird ein Auswahlfeld angezeigt, mit dem Sie eine Plattform auswählen können. In diesem Fall ist es sinnvoll, den Namen der Plattform anzugeben, es sind jedoch beispielsweise keine finanziellen Details der Plattform erforderlich.
Luc Franken
16

Dies ist eine der grundlegenden Fragen beim Entwurf von REST-APIs. Jeder Designer stellt sich diese Frage am ersten Tag. Sorry, aber die Antwort ist "es kommt darauf an". Jeder Ansatz hat Vor- und Nachteile, und Sie müssen nur eine Entscheidung treffen und mitmachen.

RibaldEddie
quelle
10
Das ist überhaupt nicht hilfreich. OP selbst wusste, "es kommt darauf an und jeder Ansatz hat Vor- und Nachteile". Sie sollten erklären, worauf es ankommt, oder zumindest ein Beispiel geben.
Pratik Singhal
5

Ich schließe mich dem hier vorgestellten Ansatz an: https://www.slideshare.net/stormpath/rest-jsonapis

Schließen Sie die verschachtelte Ressource als Links in die übergeordnete Ressource ein. Stellen Sie währenddessen einen Erweiterungsparameter im übergeordneten Endpunkt bereit.

Meiner Meinung nach ist dies in den meisten Fällen ein effizienter und flexibler Weg.

Wei Qiu
quelle
2
Ich mag diesen Ansatz. Für alle, die sich fragen, beginnt dies bei SLIDE 57 in der verknüpften Diashow.
Adam Plocher