web-dev-qa-db-fra.com

REST API - L'API doit-elle renvoyer des objets JSON imbriqués?

En ce qui concerne les API JSON, est-ce une bonne pratique d'aplatir les réponses et d'éviter les objets JSON imbriqués?

Par exemple, disons que nous avons une API similaire à IMDb mais pour les jeux vidéo. Il existe quelques entités, Game, Platform, ESRBRating et GamePlatformMap qui mappent les jeux et les plates-formes.

Disons que vous demandez/game/1 qui récupère le jeu avec l'ID 1 et renvoie l'objet de jeu avec les plates-formes et esrbRating imbriquées.

{
  "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"
  }
}

Si vous utilisez quelque chose comme JPA/Hibernate, cela peut automatiquement le faire pour vous s'il est défini sur FETCH.EAGER.

L'autre option est de simplement simplifier l'API et d'ajouter plus de points de terminaison.

Dans ce cas, lorsque/game/1 est demandé, seul l'objet de jeu est renvoyé.

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

Si vous voulez les plates-formes et/ou ESRBRating, vous devrez appeler ce qui suit:

/ jeu/1/plateforme/jeu/1/esrb

Cette méthode semble pouvoir potentiellement ajouter plusieurs appels supplémentaires au serveur en fonction des données dont le client a besoin et du moment où il en a besoin.

Il y a eu une dernière pensée que j'ai eue où vous auriez quelque chose comme ça retourné.

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

Cependant, cela suppose qu'ils n'ont pas besoin des ID ou de toute autre information pouvant être associée à ces objets de plate-forme.

Je demande en général quelle est la meilleure façon de structurer vos objets JSON renvoyés par votre API. Devriez-vous essayer de rester aussi près de vos entités que possible, ou est-ce bien d'utiliser des objets de domaine ou des objets de transfert de données? Je comprends que les méthodes auront des compromis, soit plus de travail sur la couche d'accès aux données, soit plus de travail pour le client.

J'aimerais également entendre une réponse concernant l'utilisation de Spring MVC comme technologie de backend pour l'API, avec JPA/Hibernate ou MyBatis pour la persistance.

41
greyfox

Une autre alternative (en utilisant HATEOAS). C'est simple, surtout dans la pratique, vous ajoutez une balise de liens dans le json en fonction de votre utilisation de 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: [] },
  ]
}

Vous pouvez bien sûr intégrer toutes les données dans toutes les listes, mais ce sera probablement beaucoup trop de données. De cette façon, vous pouvez incorporer les données requises, puis en charger plus si vous voulez vraiment travailler avec.

L'implémentation technique peut contenir la mise en cache. Vous pouvez mettre en cache les liens et les noms des plates-formes dans l'objet de jeu et les envoyer instantanément sans avoir à charger du tout l'api des plates-formes. Ensuite, si nécessaire, vous pouvez le charger.

Vous voyez par exemple que j'ai ajouté des informations de formulaire. Je l'ai fait pour vous montrer qu'il peut y avoir beaucoup plus d'informations dans un objet json détaillé que vous ne voudriez même en charger dans la liste des jeux.

11
Luc Franken

C'est l'une de ces questions de base en ce qui concerne la conception de l'API REST. Chaque concepteur se pose cette question le premier jour. Désolé mais la réponse est "cela dépend". Chaque approche a des avantages et des inconvénients. contre et vous aurez juste besoin de prendre une décision et d’y aller.

16
RibaldEddie

J'appuie l'approche présentée ici https://www.slideshare.net/stormpath/rest-jsonapis

En bref, incluez la ressource imbriquée en tant que liens dans la ressource parent, en attendant, fournissez un paramètre de développement dans le point de terminaison parent.

À mon avis, c'est une manière qui est efficace et flexible dans la plupart des cas.

5
Wei Qiu