it-swarm.com.de

Standard-JSON-API-Antwortformat?

Gibt es Standards oder Best Practices für die Strukturierung von JSON-Antworten über eine API? Offensichtlich sind die Daten jeder Anwendung unterschiedlich, so dass ich mich nicht um, sondern um die "Antwort-Platte" kümmere, wenn Sie so wollen. Ein Beispiel für das, was ich meine:

Erfolgreiche Anfrage:

{
  "success": true,
  "payload": {
    /* Application-specific data would go here. */
  }
}

Fehlgeschlagene Anfrage:

{
  "success": false,
  "payload": {
    /* Application-specific data would go here. */
  },
  "error": {
    "code": 123,
    "message": "An error occurred!"
  }
}
570
FtDRbwLXw6

Ja, es gibt ein paar Standards (wenn auch einige Freiheiten bei der Definition von Standard):

  1. JSON-API - Die JSON-API behandelt nicht nur Antworten, sondern auch das Erstellen und Aktualisieren von Ressourcen.
  2. JSend - Einfach und wahrscheinlich was Sie bereits tun.
  3. OData JSON Protocol - Sehr kompliziert.
  4. HAL - Wie OData, aber mit dem Ziel, HATEOAS like zu sein.

Es gibt auch JSON-API-Beschreibungsformate:

  • Swagger
    • JSON-Schema (wird von swagger verwendet, aber Sie können es eigenständig verwenden)
  • WADL in JSON
  • RAML
  • HAL weil HATEOAS in der Theorie selbstbeschreibend ist.
529
Adam Gent

Google JSON-Anleitung

Erfolgsantwort zurück data

{
  "data": {
    "id": 1001,
    "name": "Wing"
  }
}

Fehlerantwortrückgabe error

{
  "error": {
    "code": 404,
    "message": "ID not found"
  }
}

wenn Ihr Client JS ist, können Sie mit if ("error" in response) {} prüfen, ob ein Fehler vorliegt.

150
Steely Wing

Ich denke, ein Defacto-Standard ist nicht wirklich aufgetaucht (und darf niemals). Aber trotzdem, hier ist mein Take:

Erfolgreiche Anfrage:

{
  "status": "success",
  "data": {
    /* Application-specific data would go here. */
  },
  "message": null /* Or optional success message */
}

Fehlgeschlagene Anfrage:

{
  "status": "error",
  "data": null, /* or optional error payload */
  "message": "Error xyz has occurred"
}

Vorteil: Gleiche Top-Level-Elemente in Erfolgs- und Fehlerfällen

Nachteil: Kein Fehlercode, aber wenn Sie möchten, können Sie entweder den Status in einen Code (Erfolg oder Fehler) ändern, -oder- Sie können ein weiteres Element der obersten Ebene namens "Code" hinzufügen.

93
trungly

Angenommen, Ihre Frage bezieht sich auf REST Webservices-Design und genauer auf Erfolg/Fehler.

Ich denke, es gibt 3 verschiedene Arten von Designs.

  1. Verwenden Sie only HTTP Status code, um anzugeben, ob ein Fehler aufgetreten ist, und versuchen Sie, sich auf die Standardcodes zu beschränken (normalerweise sollte dies ausreichen).

    • Pro: Es ist ein Standard unabhängig von Ihrer API.
    • Nachteile: Weniger Informationen darüber, was wirklich passiert ist.
  2. Verwenden Sie HTTP Status + json body (auch wenn es ein Fehler ist). Definieren Sie eine einheitliche Struktur für Fehler (z. B. Code, Nachricht, Grund, Typ usw.), und verwenden Sie sie für Fehler. Wenn dies der Fall ist, geben Sie einfach die erwartete Json-Antwort zurück.

    • Pros: Immer noch Standard, wenn Sie die vorhandenen HTTP-Statuscodes verwenden und einen Json zurückgeben, der den Fehler beschreibt (Sie geben weitere Informationen dazu an, was passiert ist). 
    • Nachteile: Der Ausgabe-Json hängt davon ab, ob es sich um einen Fehler oder Erfolg handelt.
  3. Vergessen Sie den http-Status (z. B. immer Status 200), verwenden Sie immer json und fügen Sie im Stammverzeichnis der Antwort eine boolesche responseValid und ein Fehlerobjekt (Code, Nachricht usw.) hinzu, das bei einem Fehler aufgefüllt wird Andernfalls werden die anderen Felder (Erfolg) ausgefüllt.

    • Vorteile: Der Client befasst sich nur mit dem Hauptteil der Antwort, der eine Json-Zeichenfolge ist, und ignoriert den Status (?). 

    • Nicht so gut: The less standard.

Es liegt an Ihnen zu wählen :)

Abhängig von der API würde ich 2 oder 3 wählen (ich ziehe 2 für json rest apis vor) .. Eine andere Sache, die ich beim Entwerfen von REST -Api erfahren habe, ist die Wichtigkeit der Dokumentation für jede Ressource (URL): die Parameter , den Körper, die Antwort, die Header usw. + Beispiele.

Ich würde Ihnen auch empfehlen, Jersey zu verwenden (jax-rs-Implementierung) + genson (Java/Json-Datenbindungsbibliothek) ..__ Sie müssen nur Genson + Jersey in Ihrem Klassenpfad ablegen und Json wird automatisch unterstützt.

EDIT:

  • Lösung 2 ist am schwierigsten zu implementieren, aber der Vorteil ist, dass Sie Ausnahmen gut handhaben können und nicht nur Geschäftsfehler. Der anfängliche Aufwand ist wichtiger, aber Sie gewinnen auf lange Sicht.

  • Lösung 3 ist sowohl auf Server- als auch auf Client-Basis einfach zu implementieren, aber es ist nicht so schön, da Sie die Objekte, die Sie zurückgeben möchten, in ein Antwortobjekt kapseln müssen, das auch den responseValid + -Fehler enthält.

67
eugen

Ich werde nicht so arrogant sein zu behaupten, dass dies ein Standard ist, also werde ich das "Ich bevorzuge" -Formular verwenden. 

Ich bevorzuge eine knappe Antwort (beim Anfordern einer Liste von/Artikeln möchte ich ein JSON-Array von Artikeln). 

In meinen Entwürfen verwende ich HTTP für den Statusbericht. Ein 200 gibt nur die Nutzlast zurück. 

400 gibt eine Nachricht zurück, was mit der Anforderung falsch war:

{"message" : "Missing parameter: 'param'"}

Return 404 falls das Modell/der Controller/URI nicht existiert 

Wenn ein Fehler bei der Verarbeitung auf meiner Seite aufgetreten ist, sende ich 501 mit einer Nachricht: 

{"message" : "Could not connect to data store."}

Aus dem, was ich gesehen habe, sind einige REST-ish-Frameworks in dieser Richtung zu finden.

Begründung :

JSON soll ein Payload - Format sein, es ist kein Sitzungsprotokoll. Die ganze Idee der ausführlichen Session-ish-Payloads stammt aus der XML/SOAP-Welt und verschiedenen fehlgeleiteten Optionen, die diese aufgeblähten Designs hervorgebracht haben. Nachdem wir erkannt hatten, dass das alles heftige Kopfschmerzen hatte, war es das Wichtigste von REST/JSON, es zu KISS und sich an HTTP zu halten. Ich glaube nicht, dass es etwas entferntes standard in JSend gibt und vor allem nicht mit dem ausführlicheren unter ihnen. XHR reagiert auf die HTTP-Antwort. Wenn Sie jQuery für Ihre AJAX verwenden (wie die meisten), können Sie try/catch und done()/fail() Rückrufe verwenden, um Fehler zu erfassen. Ich kann nicht erkennen, dass das Einkapseln von Statusberichten in JSON nützlicher ist.

17
Bojan Markovic

Folgendes ist das Json-Format, das Instagram verwendet

{
    "meta": {
         "error_type": "OAuthException",
         "code": 400,
         "error_message": "..."
    }
    "data": {
         ...
    },
    "pagination": {
         "next_url": "...",
         "next_max_id": "13872296"
    }
}
16
Muhammad Amin

Für das, was es wert ist, mache ich das anders. Ein erfolgreicher Aufruf enthält nur die JSON-Objekte. Ich brauche kein JSON-Objekt auf höherer Ebene, das ein Erfolgsfeld enthält, das true angibt, und ein Nutzdatenfeld, das das JSON-Objekt enthält. Ich gebe nur das entsprechende JSON-Objekt mit 200 oder was auch immer im Bereich von 200 für den HTTP-Status im Header angemessen ist.

Wenn jedoch ein Fehler auftritt (etwas in der 400-Familie), gebe ich ein wohlgeformtes JSON-Fehlerobjekt zurück. Wenn der Client beispielsweise einen Benutzer mit einer E-Mail-Adresse und einer Telefonnummer postet und eine davon fehlerhaft ist (d. H. Ich kann sie nicht in meine zugrunde liegende Datenbank einfügen), gebe ich Folgendes zurück:

{
  "description" : "Validation Failed"
  "errors" : [ {
    "field" : "phoneNumber",
    "message" : "Invalid phone number."
  } ],
}

Wichtige Bits hier sind, dass die Eigenschaft "Feld" genau mit dem JSON-Feld übereinstimmen muss, das nicht überprüft werden konnte. Auf diese Weise können Kunden genau wissen, was mit ihrer Anfrage schief gelaufen ist. Außerdem befindet sich "message" im Gebietsschema der Anforderung. Wenn sowohl "emailAddress" als auch "phoneNumber" ungültig sind, enthält das Array "errors" Einträge für beide. Ein 409 (Konflikt) JSON-Antworttextkörper könnte folgendermaßen aussehen:

{
  "description" : "Already Exists"
  "errors" : [ {
    "field" : "phoneNumber",
    "message" : "Phone number already exists for another user."
  } ],
}

Mit dem HTTP-Statuscode und diesem JSON hat der Client alles, was er benötigt, um auf deterministische Weise auf Fehler zu reagieren, und er erstellt keinen neuen Fehlerstandard, der versucht, HTTP-Statuscodes zu ersetzen. Beachten Sie, dass diese nur für den Bereich von 400 Fehlern auftreten. Für alles im 200er-Bereich kann ich nur das zurückgeben, was angemessen ist. Für mich ist es oft ein HAL-ähnliches JSON-Objekt, aber das spielt hier keine Rolle.

Das einzige, was ich über das Hinzufügen dachte, war ein numerischer Fehlercode, entweder in den Array-Fehlern "errors" oder in der Wurzel des JSON-Objekts. Aber bisher haben wir es nicht gebraucht. 

13
robert_difalco

Der RFC 7807: Problemdetails für HTTP-APIs ist momentan das, was einem offiziellen Standard am nächsten kommt.

9
Berislav Lopac

Auf die übrigen Antwortformate großer Softwaregiganten - Google, Facebook, Twitter, Amazon und andere - gibt es keine Vereinbarung, obwohl in den Antworten oben viele Links angegeben wurden, bei denen einige versucht haben, das Antwortformat zu standardisieren. 

Da die Bedürfnisse der APIs unterschiedlich sein können, ist es sehr schwierig, alle an Bord zu holen und sich auf ein bestimmtes Format zu einigen. Wenn Sie Millionen von Benutzern verwenden, die Ihre API verwenden, warum sollten Sie Ihr Antwortformat ändern?

Nachfolgend meine Meinung zu dem Antwortformat, das von Google, Twitter, Amazon und einigen Posts im Internet inspiriert wurde:

https://github.com/adnan-kamili/rest-api-response-format

Swagger-Datei:

https://github.com/adnan-kamili/swagger-sample-template

8
adnan kamili

Der Sinn von JSON ist, dass es vollkommen dynamisch und flexibel ist. Biegen Sie es nach Belieben, denn es handelt sich lediglich um eine Reihe von serialisierten JavaScript-Objekten und -Arrays, die in einem einzigen Knoten verwurzelt sind.

Welchen Typ der Wurzelknoten hat, bleibt Ihnen überlassen, was er enthält, bleibt Ihnen überlassen. Ob Sie die Metadaten zusammen mit der Antwort senden, bleibt Ihnen überlassen, ob Sie den MIME-Typ auf application/json setzen oder ihn wie text/plain belassen Sie (solange Sie wissen, wie Sie mit den Edge-Fällen umgehen).

Erstellen Sie ein leichtes Schema, das Sie mögen.
Persönlich habe ich herausgefunden, dass Analytics-Tracking und mp3/ogg Serving und Image-Gallery Serving und Text-Messaging und Netzwerkpakete für Online-Spiele sowie Blog-Posts und Blog-Kommentare all havesehr unterschiedliche Anforderungenin Bezug auf das, was gesendet und empfangen wird und wie sie verbraucht werden sollen.

Das Letzte, was ich möchte, wenn ich all das mache, ist zu versuchen, jeden mit demselben Boilerplate-Standard konform zu machen, der auf XML2.0 oder so etwas basiert.

Das heißt, es gibt viel zu sagen, wenn man Schemata verwendet, die füryousinnvoll sind und gut durchdacht sind.
Lesen Sie einfach einige API-Antworten, notieren Sie sich, was Ihnen gefällt, kritisieren Sie, was Sie nicht tun, schreiben Sie diese Kritik auf und verstehen Sie, warum sie Sie auf die falsche Art reiben, und überlegen Sie dann, wie Sie das Gelernte auf das anwenden können, was Sie brauchen.

7
Norguard

JSON-RPC 2.0 definiert ein Standardanforderungs- und Antwortformat und ist nach dem Arbeiten mit REST -APIs ein Hauch von Frischluft.

4
dnault

In Bezug auf Ihr zweites Beispiel gilt die JSON-Spezifikation verbietet dies :

Die Daten und Fehler der Mitglieder DÜRFEN NICHT im selben Dokument vorhanden sein.

0
Soapr

Ich habe etwas recherchiert und festgestellt, dass das häufigste Format für die Rückgabe von Fehlern (Ausnahmen) eine Struktur dieses Formulars ist:

{
   "error": {
      "code": "400",
      "message": "main error message here",
      "target": "approx what the error came from",
      "details": [
         {
            "code": "23-098a",
            "message": "Disk drive has frozen up again.  It needs to be replaced",
            "target": "not sure what the target is"
         }
      ],
      "innererror": {
         "trace": [ ... ],
         "context": [ ... ]
      }
   }
}

Dies ist das Format, das vom OASIS-Datenstandard OASIS OData vorgeschlagen wird, und scheint die Standardoption auf dem Markt zu sein, es scheint jedoch zu diesem Zeitpunkt keine hohen Akzeptanzraten zu geben. Dieses Format entspricht der JSON-RPC-Spezifikation.

Die vollständige Open Source-Bibliothek, die dies implementiert, finden Sie unter: Mendocino JSON Utilities . Diese Bibliothek unterstützt die JSON-Objekte sowie die Ausnahmen.

Die Details werden in meinem Blogbeitrag zur Fehlerbehandlung in der JSON REST - API beschrieben.

0
AgilePro