モデルとマッピングテンプレートの使用
API Gateway では、API のメソッドリクエストは、バックエンドで必要となる、該当する統合リクエストペイロードとは異なる形式のペイロードを受け取ることができます。同様に、バックエンドは、フロントエンドで予期されるメソッドレスポンスペイロードとは異なる統合レスポンスペイロードを返す場合があります。API Gateway では、マッピングテンプレートを使用して、ペイロードをメソッドリクエストから該当する統合リクエストにマッピングしたり、統合レスポンスから該当するメソッドレスポンスにマッピングしたりできます。
マッピングテンプレートは、Velocity Template Language (VTL)
ペイロードでは、JSON スキーマのドラフト 4
モデル
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 つの文字列 (fruit
とvegetables
) の配列です。 -
bins
プロパティは、category
、type
、price
、unit
、および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 データのルートオブジェクトには、
department
、categories
、bins
プロパティが格納されます。 -
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 データの形式とそれらのモデルについては、以下の例を参照してください。
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
マッピングテンプレートでは、基盤となるデータが 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 を呼び出して kind
、suggestedPrice
、および available
の各プロパティを読み取ることで、GroceryStoreOutputModel[i].kind
、GroceryStoreOutputModel[i].suggestedPrice
、および GroceryStoreOutputModel[i].available
の各プロパティ値を取得できます。モデルが指定されていない場合、API Gateway は空のモデルを使用してデフォルト UDT を作成します。この場合、厳密に型指定された SDK を使用して、これらのプロパティを読み取ることはできません。
より複雑なマッピングテンプレートを試すには、以下の例を参照してください。
API Gateway でマッピングテンプレートを試すには、「レスポンスペイロードをマッピングする」の「ステップ 5: メソッドをセットアップしてテストする」の手順に従います。