Arbeiten mit Modellen und Mapping-Vorlagen - Amazon API Gateway

Arbeiten mit Modellen und Mapping-Vorlagen

In API Gateway kann eine API-Methodenanforderung eine Nutzlast in einem anderen Format als dem der entsprechenden Integrationsanforderungsnutzlast entgegennehmen, das das Backend erfordert. Das Backend wiederum kann eine Integrationsantwortnutzlast zurückgeben, die nicht der Methodenantwortnutzlast entspricht, die das Frontend erwartet. In Amazon API Gateway können Sie Mapping-Vorlagen verwenden, um die Nutzlast einer Methodenanforderung der entsprechenden Integrationsanforderung zuzuordnen bzw. die Nutzlast einer Integrationsanforderung der entsprechenden Methodenantwort zuzuordnen.

Eine Mapping-Vorlage ist ein in Velocity Template Language (VTL) ausgedrücktes Skript, dass mithilfe von JSONPath-Ausdrücken auf die Nutzlast angewendet wird.

Die Nutzlast kann ein dem JSON-Schema Entwurf 4 entsprechendes Datenmodell umfassen. Sie müssen das Modell definieren, damit API Gateway ein SDK generiert oder eine grundlegende Anfragevalidierung für Ihre API ermöglicht. Sie müssen kein Modell definieren, um eine Mapping-Vorlage zu erstellen. Ein Modell kann Ihnen jedoch bei der Erstellung einer Vorlage helfen, da API Gateway einen Vorlagenentwurf auf der Grundlage eines bereitgestellten Modells generiert.

Modelle

In API Gateway definiert ein Modell die Datenstruktur eines Payloads. In API Gateway werden Modelle unter Verwendung des JSON-Schemaentwurfs 4 definiert.

Das folgende JSON-Objekt beschreibt Musterdaten, die den Bestand an Obst und Gemüse in der Lebensmittelabteilung eines Supermarkts beschreiben.

Nehmen wir einmal an, für die Verwaltung des Bestands an Obst und Gemüse in der Lebensmittelabteilung eines Supermarkts wird eine API verwendet. Wenn ein Manager den aktuellen Bestand vom Backend abfragt, sendet der Server die folgende Antwortnutzlast zurück:

{ "department": "produce", "categories": [ "fruit", "vegetables" ], "bins": [ { "category": "fruit", "type": "apples", "price": 1.99, "unit": "pound", "quantity": 232 }, { "category": "fruit", "type": "bananas", "price": 0.19, "unit": "each", "quantity": 112 }, { "category": "vegetables", "type": "carrots", "price": 1.29, "unit": "bag", "quantity": 57 } ] }

Das JSON-Objekt hat drei Eigenschaften:

  • Die Eigenschaft department umfasst einen Zeichenfolgenwert (produce).

  • Die Eigenschaft categories ist ein Array aus zwei Zeichenfolgen: fruit und vegetables.

  • Die bins-Eigenschaft ist ein Array von Objekten, die die Zeichenfolgen- oder Zahleneigenschaften von category, type, price, unit und quantity aufweisen.

Wir können das folgende JSON-Schema verwenden, um das Modell für die vorhergehenden Daten zu definieren:

{ "$schema": "http://json-schema.org/draft-04/schema#", "title": "GroceryStoreInputModel", "type": "object", "properties": { "department": { "type": "string" }, "categories": { "type": "array", "items": { "type": "string" } }, "bins": { "type": "array", "items": { "type": "object", "properties": { "category": { "type": "string" }, "type": { "type": "string" }, "price": { "type": "number" }, "unit": { "type": "string" }, "quantity": { "type": "integer" } } } } } }

Für das obige Beispielmodell gilt:

  • Das Objekt $schema stellt eine gültige JSON-Schema-Versionskennung dar. In diesem Beispiel bezieht es sich auf das JSON-Schema Entwurf v4.

  • Das Objekt title ist eine lesbare Kennung des Modells. In unserem Beispiel lautet diese GroceryStoreInputModel.

  • Das Konstrukt der obersten Ebene oder Stammkonstrukt in den JSON-Daten ist ein Objekt.

  • Das Stammobjekt in den JSON-Daten enthält die Eigenschaften department, categories und bins.

  • Die Eigenschaft department ist ein Zeichenfolgenobjekt in den JSON-Daten.

  • Die Eigenschaft categories ist ein Array in den JSON-Daten. Das Array enthält Zeichenfolgenwerte in den JSON-Daten.

  • Die Eigenschaft bins ist ein Array in den JSON-Daten. Das Array enthält Objekte in den JSON-Daten. Alle diese Objekte in den JSON-Daten enthalten eine Zeichenfolge category, eine Zeichenfolge type, eine Zahl price, eine Zeichenfolge unit und eine Ganzzahl (eine Zahl ohne Bruchteil oder Exponent) quantity.

Alternativ können Sie auch einen Teil dieses Schemas (z. B. die Elementdefinition des Arrays bins) in einem separaten Abschnitt derselben Datei einschließen und das Primitiv $ref verwenden, um in anderen Teilen des Schemas auf diese wiederverwendbare Definition zu verweisen. Mit $ref kann die vorhergehende Modelldefinitionsdatei wie folgt ausgedrückt werden:

{ "$schema": "http://json-schema.org/draft-04/schema#", "title": "GroceryStoreInputModel", "type": "object", "properties": { "department": { "type": "string" }, "categories": { "type": "array", "items": { "type": "string" } }, "bins": { "type": "array", "items": { "$ref": "#/definitions/Bin" } } }, "definitions": { "Bin" : { "type": "object", "properties": { "category": { "type": "string" }, "type": { "type": "string" }, "price": { "type": "number" }, "unit": { "type": "string" }, "quantity": { "type": "integer" } } } } }

Der Abschnitt definitions enthält die Schemadefinition des Elements Bin, auf das im Array bins mit "$ref": "#/definitions/Bin" verwiesen wird. Wenn Sie wiederverwendbare Definitionen auf diese Weise verwenden, ist die Modelldefinition leichter lesbar.

Darüber hinaus können Sie auch auf ein anderes Schemamodell in einer externen Modelldatei verweisen, indem Sie die URL dieses Modells als Wert der Eigenschaft $ref festlegen: "$ref": "https://apigateway.amazonaws.com/restapis/{restapi_id}/models/{model_name}". Ein Beispiel: Sie verfügen über das folgende umfassende Modell mit dem Namen Bin, das unter eine API mit dem Bezeichner fugvjdxtri erstellt wurde:

{ "$schema": "http://json-schema.org/draft-04/schema#", "title": "GroceryStoreInputModel", "type": "object", "properties": { "Bin" : { "type": "object", "properties": { "category": { "type": "string" }, "type": { "type": "string" }, "price": { "type": "number" }, "unit": { "type": "string" }, "quantity": { "type": "integer" } } } } }

Dann können Sie wie folgt in GroceryStoreInputModel derselben API auf dieses verweisen:

{ "$schema": "http://json-schema.org/draft-04/schema#", "title": "GroceryStoreInputModel", "type": "object", "properties": { "department": { "type": "string" }, "categories": { "type": "array", "items": { "type": "string" } }, "bins": { "type": "array", "items": { "$ref": "https://apigateway.amazonaws.com/restapis/fugvjdxtri/models/Bin" } } } }

Die verweisenden Modelle und die Modelle, auf die verwiesen wird, müssen aus derselben API stammen.

Die Beispiele verwenden keinerlei erweiterte JSON-Schemafunktionen, wie das Angeben erforderlicher Elemente, Mindest- und Maximalwerte (für zulässige Zeichenfolgenlängen, numerische Werte und Array-Elementlängen) und reguläre Ausdrücke. Weitere Informationen finden Sie unter Introducing JSON und JSON Schema Entwurf 4.

In den folgenden Beispielen finden Sie Informationen zu komplexeren JSON-Datenformaten und ihren Modellen:

Um mit Modellen in API Gateway zu experimentieren, folgen Sie den Anweisungen in Zuweisen der Antwortnutzlast (insbesondere Schritt 2: Erstellen von Modellen).

Mapping-Vorlagen

Wenn das Backend die Abfrageergebnisse (dargestellt im Abschnitt Modelle) zurückgibt, wird der Manager der Lebensmittelabteilung sie möglicherweise wie folgt lesen wollen:

{ "choices": [ { "kind": "apples", "suggestedPrice": "1.99 per pound", "available": 232 }, { "kind": "bananas", "suggestedPrice": "0.19 per each", "available": 112 }, { "kind": "carrots", "suggestedPrice": "1.29 per bag", "available": 57 } ] }

Um dies zu ermöglichen, müssen wir API Gateway eine Mapping-Vorlage zur Übersetzung der Daten aus dem Backend-Format zur Verfügung stellen. Die folgende Mapping-Vorlage tut dies.

#set($inputRoot = $input.path('$')) { "choices": [ #foreach($elem in $inputRoot.bins) { "kind": "$elem.type", "suggestedPrice": "$elem.price per $elem.unit", "available": $elem.quantity }#if($foreach.hasNext),#end #end ] }

Betrachten wir jetzt einige Details der obigen Ausgabe-Mapping-Vorlage:

  • Die Variable $inputRoot stellt in den ursprünglichen JSON-Daten aus dem vorherigen Abschnitt das Stammobjekt dar. Die Variablen in einer Ausgabe-Mapping-Vorlage sind den ursprünglichen JSON-Daten zugeordnet, nicht dem gewünschten umgewandelten JSON-Datenschema.

  • Das Array choices in der Ausgabe-Mapping-Vorlage wird von dem Array bins mit dem Stammobjekt in den ursprünglichen JSON-Daten ($inputRoot.bins) zugeordnet.

  • In der Ausgabe-Mapping-Vorlage wird jedes der Objekte im Array choices (dargestellt durch $elem) von den entsprechenden Objekten im Array bins innerhalb des Stammobjekts in den ursprünglichen JSON-Daten zugeordnet.

  • In der Ausgabe-Mapping-Vorlage werden die Werte der Objekte choices und kind (dargestellt durch available und $elem.type) für jedes Objekt im Objekt $elem.quantity von den entsprechenden Werten der Objekte type und value in jedem Objekt des Arrays bins der ursprünglichen JSON-Daten zugeordnet.

  • In der Ausgabe-Mapping-Vorlage ist der Wert des Objekts choices für jedes Objekt im Objekt suggestedPrice eine Verkettung der entsprechenden Werte der Objekte price bzw. unit in jedem Objekt in den ursprünglichen JSON-Daten. Die Werte sind dabei durch das Wort per getrennt.

Weitere Informationen zur Velocity Template Language finden Sie in der Apache Velocity – VTL-Reference. Weitere Informationen zu JSONPath finden Sie unter JSONPath – XPath for JSON.

Die Mapping-Vorlage geht davon aus, dass die zugrundeliegenden Daten zu einem JSON-Objekt gehören. Es ist nicht erforderlich, ein Modell für die Daten zu definieren. Als API-Entwickler kennen Sie die Datenformate für das Frontend und das Backend. Dieses Wissen hilft Ihnen, die erforderlichen Mappings eindeutig zu definieren.

Um ein SDK für die API zu erzeugen, werden die vorherigen Daten als sprachspezifisches Objekt zurückgegeben. Bei stark typisierten Sprachen wie Java, Objective-C oder Swift entspricht das Objekt einem benutzerdefinierten Datentyp (UDT). API Gateway erstellt eine solche UDT, wenn Sie ihm ein Datenmodell zur Verfügung stellen. Für das vorangegangene Methodenantwortbeispiel können Sie in der Integrationsantwort das folgende Nutzlastmodell definieren:

{ "$schema": "http://json-schema.org/draft-04/schema#", "title": "GroceryStoreOutputModel", "type": "object", "properties": { "choices": { "type": "array", "items": { "type": "object", "properties": { "kind": { "type": "string" }, "suggestedPrice": { "type": "string" }, "available": { "type": "integer" } } } } } }

In diesem Modell wird das JSON-Schema wie folgt ausgedrückt:

  • Das Objekt $schema stellt eine gültige JSON-Schema-Versionskennung dar. In diesem Beispiel bezieht es sich auf das JSON-Schema Entwurf v4.

  • Das Objekt title ist eine lesbare Kennung des Modells. In unserem Beispiel lautet diese GroceryStoreOutputModel.

  • Das Konstrukt der obersten Ebene oder Stammkonstrukt in den JSON-Daten ist ein Objekt.

  • Das Stammobjekt in den JSON-Daten enthält ein Array von Objekten.

  • Jedes Objekt in diesem Array von Objekten enthält eine Zeichenfolge kind, eine Zeichenfolge suggestedPrice und eine Ganzzahl (eine Zahl ohne Bruchteil oder Exponent Teil) available.

Mit diesem Modell können Sie ein SDK aufrufen, um die Eigenschaftenwerte kind, suggestedPrice und available durch Lesen der Eigenschaften GroceryStoreOutputModel[i].kind, GroceryStoreOutputModel[i].suggestedPrice bzw. GroceryStoreOutputModel[i].available abzurufen. Wenn kein Modell zur Verfügung gestellt wird, verwendet API Gateway das leere Modell zur Erstellung einer Standard-UDT. In diesem Fall können Sie diese Eigenschaften nicht mithilfe eines stark typisierten SDK lesen.

Informationen zu komplexeren Mapping-Vorlagen finden Sie in den folgenden Beispielen:

Zum Experimentieren mit Mapping-Vorlagen in API Gateway zu folgen Sie den Anweisungen in Zuweisen der Antwortnutzlast (insbesondere Schritt 5: Konfigurieren und Testen der Methoden).