モデルとマッピングテンプレートの使用 - Amazon API Gateway

モデルとマッピングテンプレートの使用

API Gateway では、API のメソッドリクエストは、バックエンドで必要となる、該当する統合リクエストペイロードとは異なる形式のペイロードを受け取ることができます。同様に、バックエンドは、フロントエンドで予期されるメソッドレスポンスペイロードとは異なる統合レスポンスペイロードを返す場合があります。API Gateway では、マッピングテンプレートを使用して、ペイロードをメソッドリクエストから該当する統合リクエストにマッピングしたり、統合レスポンスから該当するメソッドレスポンスにマッピングしたりできます。

マッピングテンプレートは、Velocity Template Language (VTL) で表現されるスクリプトであり、JSONPath 式を使用してペイロードに適用されます。

ペイロードでは、JSON スキーマのドラフト 4 に基づくデータモデルを使用できます。このモデルは、API Gateway で SDK を生成する際や、API で基本的なリクエストの検証を有効にする際に定義する必要があります。マッピングテンプレートを作成する際にモデルを定義する必要はありません。ただし、API Gateway では指定されたモデルに基づいてテンプレート設計図が生成されるため、モデルを定義するとテンプレート作成に役立ちます。

モデル

API Gateway では、モデルはペイロードのデータ構造を定義します。API Gateway では、JSON スキーマのドラフト 4 を使用してモデルを定義します。

次の JSON オブジェクトは、よくあるスーパーマーケットの青果部門の果物または野菜の在庫を記述したサンプルデータを示しています。

スーパーマーケットの青果部門で果物と野菜の在庫を管理するための API があるとします。マネージャーからバックエンドに現在の在庫についての問い合わせがあると、サーバーは次のレスポンスペイロードを送り返します。

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

JSON オブジェクトには、3 つのプロパティがあります。

  • department プロパティは文字列値 (produce) を持ちます。

  • categories プロパティは、2 つの文字列 (fruitvegetables) の配列です。

  • bins プロパティは、categorytypepriceunit、および quantity の文字列または数値プロパティを持つオブジェクトの配列です。

上記のデータのモデルを定義するには、次の JSON スキーマを使用できます。

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

前のモデル例では、以下のようになっています。

  • $schema オブジェクトは、有効な JSON スキーマのバージョン識別子を表します。この例では、JSON スキーマのドラフト v4 を表します。

  • title オブジェクトは、人間が読めるモデルの識別子です。この例では、GroceryStoreInputModel です。

  • JSON データのトップレベル (ルート) 構造体はオブジェクトです。

  • JSON データのルートオブジェクトには、departmentcategoriesbins プロパティが格納されます。

  • department プロパティは JSON データの文字列オブジェクトです。

  • categories プロパティは JSON データの配列です。この配列には、JSON データの文字列値が格納されます。

  • bins プロパティは JSON データの配列です。この配列には、JSON データのオブジェクトが格納されます。JSON データのこれらの各オブジェクトには、category 文字列、type 文字列、price 数値、unit 文字列、quantity 整数 (小数部または指数部のない数字) が格納されます。

または、このスキーマの一部 (bins 配列の項目の定義など) を同じファイルの別のセクションに含めて、$ref プリミティブを使用して、スキーマの他の部分でこの再利用可能な定義を参照することができます。$ref を使用すると、上記のモデル定義ファイルを次のように表現できます。

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

definitions セクションには、Bin 配列で bins で参照される "$ref": "#/definitions/Bin" 項目のスキーマ定義を含めることができます。このようにして再利用可能な定義を使用すると、モデル定義は読みやすくなります。

さらに、そのモデルの URL を $ref プロパティの値 "$ref": "https://apigateway.amazonaws.com/restapis/{restapi_id}/models/{model_name}" として設定することで、外部モデルファイルで定義された別のモデルスキーマを参照することもできます。たとえば、ID fugvjdxtri を使って API で作成された、Bin という名前の次の本格的なモデルがあるとします。

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

次に、同じ API の GroceryStoreInputModel から、これを参照できます。

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

参照元および参照先モデルは、同じ API からのものである必要があります。

この例では、必須項目や、最小値と最大値 (文字列長さ、数値、配列項目) を指定したり、正規表現を使用したりするような、JSON スキーマのアドバンスト機能は使用していません。詳細については、「JSON のご紹介」および「JSON スキーマのドラフト 4」を参照してください。

より複雑な JSON データの形式とそれらのモデルについては、以下の例を参照してください。

API Gateway でモデルを試すには、「レスポンスペイロードをマッピングする」の「ステップ 2: モデルを作成する」の手順に従います。

マッピングテンプレート

バックエンドから返されるクエリ結果 (モデル セクション) は、次のように表示されると青果部門のマネージャーに役立つと思われます。

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

これを有効にするには、データをバックエンド形式から変換するマッピングテンプレートを API Gateway に提供する必要があります。それを行うのは次のマッピングテンプレートです。

#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 ] }

この出力マッピングテンプレートの詳細について以下に説明します。

  • $inputRoot 変数は、前のセクションにおける元の JSON データのルートオブジェクトです。出力マッピングテンプレートの変数は、変換後の JSON データスキーマではなく、元の JSON データにマッピングされています。

  • 出力マッピングテンプレートの choices 配列は、元の JSON データのルートオブジェクト (bins) の $inputRoot.bins 配列からマッピングされます。

  • 出力マッピングテンプレートで、choices 配列の各オブジェクト ($elem) は、元の JSON データのルートオブジェクト内の bins 配列の対応するオブジェクトからマッピングされます。

  • 出力マッピングテンプレートの choices オブジェクト内のオブジェクトごとに、kind オブジェクトと available オブジェクトの値 ($elem.type および $elem.quantity) は、元の JSON データの type 配列内のオブジェクトごとの value オブジェクトと bins オブジェクトの対応する値からそれぞれマッピングされます。

  • 出力マッピングテンプレートの choices オブジェクト内のオブジェクトごとに、suggestedPrice オブジェクトの値は、元の JSON データのオブジェクトごとの price オブジェクトと unit オブジェクトのそれぞれ対応する値の連結であり、各値は per という単語で区切られます。

Velocity Template Language の詳細については、「Apache Velocity - VTL Reference」を参照してください。JSONPath の詳細については、「JSONPath - XPath for JSON」を参照してください。

マッピングテンプレートでは、基盤となるデータが JSON オブジェクトであることを前提としています。データのモデルを定義する必要はありません。API 開発者は、フロントエンドとバックエンドの両方のデータ形式を知っています。その知識があれば、形式を混同することはなく、必要なマッピングを定義できます。

API 用の SDK を生成するために、上記のデータが言語固有のオブジェクトとして返されます。Java、Objective-C、Swift などの厳密に型指定された言語では、オブジェクトはユーザー定義データ型 (UDT) に対応します。API Gateway にデータモデルを提供すると、このような UDT が作成されます。上記のメソッドレスポンス例では、統合レスポンスで次のペイロードモデルを定義できます。

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

このモデルでは、JSON スキーマは以下のように表現されています。

  • $schema オブジェクトは、有効な JSON スキーマのバージョン識別子を表します。この例では、JSON スキーマのドラフト v4 を表します。

  • title オブジェクトは、人間が読めるモデルの識別子です。この例では、GroceryStoreOutputModel です。

  • JSON データのトップレベル (ルート) 構造体はオブジェクトです。

  • JSON データのルートオブジェクトには、オブジェクトの配列が格納されます。

  • このオブジェクトの配列内の各オブジェクトには、kind 文字列、suggestedPrice 文字列、available 整数 (小数部または指数部のない数字) が格納されます。

このモデルでは、SDK を呼び出して kindsuggestedPrice、および available の各プロパティを読み取ることで、GroceryStoreOutputModel[i].kindGroceryStoreOutputModel[i].suggestedPrice、および GroceryStoreOutputModel[i].available の各プロパティ値を取得できます。モデルが指定されていない場合、API Gateway は空のモデルを使用してデフォルト UDT を作成します。この場合、厳密に型指定された SDK を使用して、これらのプロパティを読み取ることはできません。

より複雑なマッピングテンプレートを試すには、以下の例を参照してください。

API Gateway でマッピングテンプレートを試すには、「レスポンスペイロードをマッピングする」の「ステップ 5: メソッドをセットアップしてテストする」の手順に従います。