Format de réponse API JSON Standard?
Existe-t-il des normes ou des meilleures pratiques pour structurer les réponses JSON à partir d'une API? Évidemment, les données de chaque application sont différentes, de sorte que je ne suis pas concerné, mais plutôt la "réponse standard", si vous voulez. Un exemple de ce que je veux dire:
Demande réussie:
{
"success": true,
"payload": {
/* Application-specific data would go here. */
}
}
La demande qui a Échoué:
{
"success": false,
"payload": {
/* Application-specific data would go here. */
},
"error": {
"code": 123,
"message": "An error occurred!"
}
}
12 réponses
Oui, il y a quelques normes (bien que certaines libertés sur la définition de la norme) qui ont émergé:
- API JSON - L'API JSON couvre également la création et la mise à jour des ressources, pas seulement les réponses.
- JSend - Simple et probablement ce que vous faites déjà.
- protocole json OData - très compliqué.
- HAL - comme OData mais visant à être HATEOAS comme.
Il y a aussi des API JSON formats de description:
-
Swagger
- schéma JSON (utilisé par swagger mais vous pouvez l'utiliser seul)
- WADL dans JSON
- RAML
- Hal parce que HATEOAS en théorie est auto-décrivant.
Guide Google JSON
Succès de réponse en retour data
{
"data": {
"id": 1001,
"name": "Wing"
}
}
Réponse d'Erreur de retour error
{
"error": {
"code": 404,
"message": "ID not found"
}
}
Et si votre client est JS, vous pouvez utiliser if ("error" in response) {}
pour vérifier s'il y a une erreur.
Je suppose qu'une norme de fait n'a pas vraiment émergé (et peut-être jamais). Mais peu importe, voici ma prise:
Demande réussie:
{
"status": "success",
"data": {
/* Application-specific data would go here. */
},
"message": null /* Or optional success message */
}
La demande qui a Échoué:
{
"status": "error",
"data": null, /* or optional error payload */
"message": "Error xyz has occurred"
}
Avantage: mêmes éléments de haut niveau dans les cas de réussite et d'erreur
Inconvénient: pas de code d'erreur, mais si vous le souhaitez, vous pouvez soit changer de statut pour être un code (succès ou échec),- ou - vous pouvez ajouter un autre élément de niveau supérieur nommé "code".
En supposant que votre question concerne la conception des services web REST et plus précisément le succès / erreur.
Je pense qu'il existe 3 types de design différents.
-
Utilisez uniquement le code D'état HTTP pour indiquer s'il y a eu une erreur et essayez de vous limiter aux codes standard (généralement cela devrait suffire).
- avantages: c'est un standard indépendant de votre api.
- inconvénients: moins d'informations sur ce qui s'est réellement passé.
-
Utilisation statut HTTP + corps json (même s'il s'agit d'une erreur). Définissez une structure uniforme pour les erreurs (ex: code, message, raison, type, etc.) et utilisez-la pour les erreurs, si c'est un succès, renvoyez simplement la réponse JSON attendue.
- avantages: toujours standard car vous utilisez les codes D'état HTTP existants et vous renvoyez un json décrivant l'erreur (vous fournissez plus d'informations sur ce qui s'est passé).
- inconvénients: Le JSON de sortie varie en fonction si c'est une erreur ou succès.
-
Oubliez le statut http (ex: always status 200), Utilisez toujours json et ajoutez à la racine de la réponse un responseValid booléen et un objet error (code,message,etc) qui sera rempli s'il s'agit d'une erreur sinon les autres champs (success) sont remplis.
Avantages: le client ne traite que le corps de la réponse qui est une chaîne json et ignore le statut (?).
Inconvénients: Le moins norme.
, C'est à vous de choisir :)
En fonction de l'API, je choisirais 2 ou 3 (je préfère 2 pour les API rest JSON). Une autre chose que j'ai expérimentée dans la conception de L'Api REST est l'importance de la documentation pour chaque ressource (url): les paramètres, le corps, la réponse, les en-têtes, etc + exemples.
Je vous recommande également d'utiliser jersey (implémentation JAX-rs) + genson (bibliothèque de liaison de données java/json). Vous n'avez qu'à déposer genson + maillot dans votre classpath et json est automatiquement pris en charge.
Modifier:
La Solution 2 est la plus difficile à mettre en œuvre, mais l'avantage est que vous pouvez bien gérer les exceptions et pas seulement les erreurs commerciales, l'effort initial est plus important mais vous gagnez à long terme.
La Solution 3 est facile à mettre en œuvre à la fois côté serveur et client, mais ce n'est pas si agréable que vous devrez encapsuler les objets que vous voulez retourner dans une réponse objet contenant également l'erreur responseValid+.
Je ne serai pas aussi arrogant de prétendre qu'il s'agit d'une norme, alors j'utiliserai le formulaire "je préfère".
Je préfère la réponse laconique (en demandant une liste de / articles, je veux un tableau JSON d'articles).
Dans mes conceptions, J'utilise HTTP pour le rapport d'état, Un 200 renvoie juste la charge utile.
400 renvoie un message de ce qui n'allait pas avec la demande de l':
{"message" : "Missing parameter: 'param'"}
Retour 404 si le modèle / contrôleur / URI n'existe pas
S'il y avait une erreur avec le traitement de mon côté, je reviens 501 avec un message:
{"message" : "Could not connect to data store."}
D'après ce que j'ai vu, quelques frameworks REST-ish ont tendance à suivre ces lignes.
Justification:
JSON est censé être un formatpayload , ce n'est pas un protocole de session. Toute l'idée des charges utiles verbeuses de session-ish vient du monde XML / SOAP et de divers choix erronés qui ont créé ces conceptions gonflées. Après que nous avons réalisé que tout cela était un mal de tête massif, le tout le point de repos / JSON était de L'embrasser, et d'adhérer à HTTP. Je ne pense pas qu'il y ait quelque chose à distance standard dans JSend et surtout pas avec les plus verbeux d'entre eux. XHR réagira à la réponse HTTP, Si vous utilisez jQuery pour votre AJAX (comme la plupart le font), vous pouvez utiliser try
/catch
et done()
/fail()
rappels pour capturer les erreurs. Je ne vois pas comment encapsuler des rapports d'état dans JSON est plus utile que cela.
Voici le format JSON utilisé par instagram
{
"meta": {
"error_type": "OAuthException",
"code": 400,
"error_message": "..."
}
"data": {
...
},
"pagination": {
"next_url": "...",
"next_max_id": "13872296"
}
}
Pour ce que ça vaut je le fais différemment. Un appel réussi a juste les objets JSON. Je n'ai pas besoin d'un objet JSON de niveau supérieur qui contient un champ de réussite indiquant true et un champ de charge utile qui a l'objet JSON. Je retourne simplement l'objet JSON approprié avec un 200 ou tout ce qui est approprié dans la plage 200 pour L'état HTTP dans l'en-tête.
Cependant, s'il y a une erreur (quelque chose dans la famille 400), je retourne un objet d'erreur JSON bien formé. Par exemple, si le client affiche un utilisateur avec une adresse e-mail et un numéro de téléphone et l'un d'entre eux est mal formé (c'est-à-dire que je ne peux pas l'insérer dans ma base de données sous-jacente)je retournerai quelque chose comme ceci:
{
"description" : "Validation Failed"
"errors" : [ {
"field" : "phoneNumber",
"message" : "Invalid phone number."
} ],
}
Les bits importants ici sont que la propriété "field" doit correspondre exactement au champ JSON qui n'a pas pu être validé. Cela permet aux clients de savoir exactement ce qui a mal tourné avec leur demande. En outre, "message" est dans les paramètres régionaux de la requête. Si les "emailAddress" et "phoneNumber" n'étaient pas valides, le le tableau "erreurs" contiendrait des entrées pour les deux. Un corps de réponse JSON 409 (conflit) peut ressembler à ceci:
{
"description" : "Already Exists"
"errors" : [ {
"field" : "phoneNumber",
"message" : "Phone number already exists for another user."
} ],
}
Avec le code D'état HTTP et ce JSON, le client a tout ce dont il a besoin pour répondre aux erreurs de manière déterministe et il ne crée pas de nouvelle norme d'erreur qui tente de remplacer les codes D'état HTTP. Notez que ceux-ci ne se produisent que pour la plage de 400 erreurs. Pour tout ce qui est dans la gamme 200, je peux simplement retourner tout ce qui est approprié. Pour moi, c'est souvent un objet JSON de type HAL mais qui n'a pas vraiment d'importance ici.
La seule chose que j'ai pensé ajouter était un code d'erreur numérique dans les entrées du tableau "erreurs" ou la racine de l'objet JSON lui-même. Mais jusqu'à présent, nous n'en avons pas eu besoin.
La RFC 7807: détails du problème pour les API HTTP est pour le moment la chose la plus proche d'une norme officielle.
Le point de JSON est qu'il est complètement dynamique et flexible. Pliez-le à n'importe quel caprice, car il s'agit simplement d'un ensemble d'objets et de tableaux JavaScript sérialisés, enracinés dans un seul nœud.
Ce que le type de la rootnode est à vous, ce qu'il contient est à vous, si vous envoyez des méta-données avec la réponse est à vous, si vous définissez le type mime application/json
, ou le laisser comme text/plain
est à vous (et aussi longtemps que vous savez comment gérer le bord cas).
Construisez un schéma léger que vous aimez.
Personnellement, j'ai trouvé que analytics-tracking et MP3 / OGG serving et image-gallery serving et text-messaging et network-packets pour les jeux en ligne, et blog-posts et blog-comments Tous ont exigences très différentes en termes de ce qui est envoyé et ce qui est reçu et comment ils devraient être consommés.
Donc, la dernière chose que je voudrais, en faisant tout cela, est d'essayer de rendre chacun conforme à la même norme standard, qui est basée sur XML2. 0 ou somesuch.
Cela dit, il y a beaucoup à dire pour utiliser des schémas qui ont du sens à toi et sont bien pensés.
Il suffit de lire quelques réponses API, notez ce que vous aimez, critiquez ce que vous ne faites pas, écrivez ces critiques et comprenez pourquoi elles vous frottent dans le mauvais sens, puis réfléchissez à la façon d'appliquer ce que vous avez appris à ce dont vous avez besoin.
Leur est pas d'accord sur les formats de réponse api rest de grands géants du logiciel-Google, Facebook, Twitter, Amazon et d'autres, bien que de nombreux liens ont été fournis dans les réponses ci-dessus, où certaines personnes ont essayé de normaliser le format de réponse.
Comme les besoins de L'API peuvent différer, il est très difficile d'obtenir tout le monde à bord et d'accepter un certain format. Si vous avez des millions d'utilisateurs utilisant votre API, pourquoi changeriez-vous votre format de réponse?
Voici mon point de vue le format de réponse inspiré par Google, Twitter, Amazon et certains messages sur internet:
Https://github.com/adnan-kamili/rest-api-response-format
Fichier Swagger:
JSON-RPC 2.0 définit un format standard de requête et de réponse, et est une bouffée d'air frais après avoir travaillé avec les API REST.
Meilleure réponse pour les API web que les développeurs mobiles peuvent facilement comprendre.
C'est pour la réponse "succès"
{
"ReturnCode":"1",
"ReturnMsg":"Successfull Transaction",
"ReturnValue":"",
"Data":{
"EmployeeName":"Admin",
"EmployeeID":1
}
}
C'est pour la réponse "erreur"
{
"ReturnCode": "4",
"ReturnMsg": "Invalid Username and Password",
"ReturnValue": "",
"Data": {}
}