it-swarm.com.de

Ist es eine gute Praxis, eine API-Antwortliste mit Werten als Wörterbuch zu erstellen?

Ich habe einen API-Endpunkt, der einige Statistiken zurückgibt. Derzeit sieht die Antwort so aus:

Option 1:

{
    "stats": [
                {
                    "name": "some-stats-key1",
                    "value": 10
                },
                {
                    "name": "some-stats-key2",
                    "value": 20
                }
            ],
    ... other keys
}

Aber das sieht ein bisschen komplex aus und ich weiß, wie ich es machen soll:

Option 2:

{
    "stats": {
                "some-stats-key1": 10,
                "some-stats-key2": 20
            }
    ... other keys
}

Ich verstehe, dass Option 1 einfacher zu erweitern ist, aber für Benutzer weniger komfortabel. Welche anderen Probleme kann ich mit einer dieser Optionen haben? Oder sollte ich eine Hybridlösung machen wie:

Option 3:

{
    "stats": {
                "some-stats-key1": {
                                        "name": "some-stats-key1",
                                        "value": 10
                                    },
                "some-stats-key2": {
                                        "name": "some-stats-key2",
                                        "value": 20
                                    },
            },
    ... other keys
}

Die Schlüssel "some-stats-key1" und "some-stats-key2" sind nur interne Werte, und es wird erwartet, dass der API-Benutzer sie mithilfe der Dokumentation in lesbare Namen abbildet. Alle Schlüssel sind einzigartig.

Die Reihenfolge der "Statistiken" ist nicht wichtig.

Der typische Anwendungsfall besteht darin, alle Statistiken abzurufen, Schlüssel mit lesbaren Namen abzugleichen und als Tabelle auf einer Webseite anzuzeigen. Aber derzeit kann ich nicht sagen, ob niemand später nur einen Teil der Statistiken benötigt.

Gibt es eine bewährte Methode für dieses Problem?

9
Yann

Ich würde mich für Option 2 entscheiden. Wenn der API-Konsument some-stats-key1 In etwas Lesbares konvertiert, bedeutet dies wahrscheinlich, dass er/sie eine Liste von Werten hat, an denen er/sie interessiert ist (z. B. some-stats-key1). und some-stats-key3) und wird diese Liste durchlaufen. Durch Auswahl eines JSON-Objekts wird es als Wörterbuch/Map deserialisiert, das dem Benutzer der API eine bequeme Suche bietet.

Dies ist mit Option 1 umständlicher, bei der der Verbraucher das JSON-Array durchlaufen oder ein eigenes Wörterbuch mit interessanten Schlüsseln vorab erstellen muss.

Option 3 ist mir etwas zu ausführlich, die Vervielfältigung der Schlüsselnamen gefällt mir einfach nicht.

Wenn die Erweiterbarkeit ein Problem darstellt, können Sie jederzeit eine Version 2 Ihrer API veröffentlichen, die so etwas wie zurückgibt

"stats": {
    "some-stats-key1": { "value": 10, "error-margin": 0.1 },
    "some-stats-key2": { "value": 20, "error-margin": 0.2 }
}

und behalten Sie die v1 für Abwärtskompatibilität. Die Aufrechterhaltung der Abwärtskompatibilität innerhalb einer einzelnen Version der API kann eine echte PITA sein, wenn Sie nicht die vollständige Kontrolle darüber haben, wie die API verwendet wird. Ich habe einen Verbrauch einer API von mir "break" gesehen, als ich gerade ein zusätzliches (optionales) Schlüssel-Wert-Paar hinzugefügt habe (d. H. Die Struktur nicht geändert habe).

8
Glorfindel

Die beiden Optionen bieten die klassischen Vorteile von Liste und Karte.

1) Die Liste erlaubt doppelte Einträge und behält die Reihenfolge bei. Wenn diese Funktionen wichtig sind, verwenden Sie die Liste, auch wenn sie umständlicher ist.

2) Die Karte erlaubt keine Duplikate. Die Aufrechterhaltung der Ordnung ist mit ein wenig zusätzlicher Arbeit möglich. Der große Vorteil ist die Einfachheit des Datenformats, und die Suche nach einem bestimmten Element ist trivial.

Meine Standardauswahl ist immer die einfachere Karte, aber YMMV.

7
user949300

Wenn ich Daten von einer API erhalte, überprüfe ich immer, ob alles so ist, wie ich es erwartet habe. Mein Versuch, Ihre Daten zu verarbeiten, besteht also in der Überprüfung und der tatsächlichen Verarbeitung.

In Fall 1 muss ich Folgendes überprüfen: a. Es gibt ein Array. b. Alle Elemente im Array sind Wörterbücher. c. Jedes Wörterbuch hat einen Schlüssel "Name". d. Alle Werte für den Schlüssel "Name" sind eindeutig.

In Fall 3 muss ich Folgendes überprüfen: a. Es gibt ein Wörterbuch. b. Alle Werte im Wörterbuch sind Wörterbücher. c. Jedes Wörterbuch hat einen Schlüsselnamen mit einem Wert, der mit dem Schlüssel im äußeren Wörterbuch übereinstimmt. Etwas besser.

In Fall 2 muss ich Folgendes überprüfen: a. Es gibt ein Wörterbuch.

(Natürlich muss ich auch die Werte überprüfen). Ihr Fall 2 erfordert also die geringste Überprüfung auf meiner Seite. Ich bekomme tatsächlich eine Datenstruktur, die sofort verwendbar ist.

Das einzige Problem mit 2 ist, dass es nicht erweiterbar ist. Anstatt den Wert als Zahl zu senden, können Sie auch {Wert: 10} senden, der dann abwärtskompatibel erweitert werden kann.

Redundanz ist schlecht. Das einzige, was durch Redundanz erreicht wird, ist, dass ich mehr Code schreibe und darüber nachdenke, was ich tun soll, wenn die redundanten Bits nicht übereinstimmen. Version 2 hat keine Redundanz.

3
gnasher729

Da Sie nach bewährten Methoden für das API-Design gefragt haben:

  • Ich gebe niemals eine API-Antwort zurück, die ein Objekt auf der obersten Ebene enthält. Alle Serviceaufrufe geben eine Menge (als Array) zurück, und diese Menge enthält Elemente (als Objektinstanzen). Die Anzahl der im Array zurückgegebenen Objekte ist für den Server irrelevant. Wenn der Kunde anhand der Anzahl der in der Antwort zurückgegebenen Elemente eine Bestimmung treffen muss, muss der Kunde diese Belastung durchsetzen. Wenn ein einzelnes Element erwartet wird, wird es als Einheitensatz zurückgegeben
  • Wenn ich eine API entwerfe, gehe ich nicht davon aus, zu wissen, welche spezifische Technologie meine API-Kunden verwenden werden, um diese API zu konsumieren, selbst wenn ich weiß, welche spezifische Technologie sie am wahrscheinlichsten verwenden. Meine Verantwortung ist es, meine Domain-Repräsentationen konsistent an alle Verbraucher zu kommunizieren, nicht bequem an einen bestimmten Verbraucher.
  • Wenn eine strukturelle Option vorhanden ist, mit der die Antwort zusammengestellt werden kann, hat diese Struktur Vorrang vor Optionen, die dies nicht tun
  • Ich bemühe mich zu vermeiden, Darstellungen mit unvorhersehbaren Strukturen zu erstellen.
  • Wenn die Struktur einer Darstellung vorhergesagt werden kann, sollten alle Instanzen innerhalb des Antwortsatzes dieselbe Darstellung haben und der Antwortsatz sollte intern konsistent sein.

Angesichts der von Ihnen vorgeschlagenen Strukturen würde die Struktur, die ich implementieren würde, ähnlich aussehen

[
   { /* returns only the 'common' metrics */
      "stats": [
                  {"key":"some-metric1","value":10},
                  {"key":"some-metric2","value":20}
               ]
   },
   { /* returns an optional metric in addition to the "common" metrics */
      "stats": [
                  {"key":"some-metric1","value":15},
                  {"key":"some-metric2","value":5},
                  {"key":"some-optional-metric", "value":42}
               ]
   },
   { /*returns the 'common' metrics as well as 2 candidates for "foo-bar" */
      "stats": [
                  {"key":"some-metric1", "value": 5},
                  {"key":"some-metric2", "value": 10},
                  {"key":"foo-bar-candidate", "value": 7},
                  {"key":"foo-bar-candidate", "value": 11}
               ]
   }
]
1
K. Alan Bates