使用模型和映射模板
在 API Gateway 中,API 的方法请求采用的负载格式可能与后端所需的相应集成请求负载的格式不同。同样,后端返回的集成响应负载可能不同于前端希望的方法响应负载。API Gateway 允许您使用映射模板将负载从方法请求映射到相应的集成请求,以及从集成响应映射到相应的方法响应。
映射模板是一个用 Velocity 模板语言 (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 对象有三个属性:
-
department
属性有一个字符串值 (produce
)。 -
categories
属性是由两个字符串 (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 架构草稿版本 4。 -
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}"
。例如,假设您在标识符为 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 中的模型,请按照映射响应负载中的说明操作,具体来说就是步骤 1:创建模型。
映射模板
当后端返回查询结果(在模型部分中显示)时,生产部门的经理可能会有兴趣阅读它们,如下所示:
{ "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 模板语言的更多信息,请参阅 Apache Velocity – VTL 参考
该映射模板假定基础数据为 JSON 对象。它不要求为数据定义模型。作为 API 开发人员,您需要知道前端和后端的数据格式。掌握这些信息可指导您定义必要的映射,而不会模棱两可。
要为 API 生成开发工具包,上述数据将作为特定于语言的对象而返回。对于强类型语言(如 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 架构草稿版本 4。 -
title
对象是人类可读的模型标识符。在本例中,它是GroceryStoreOutputModel
。 -
JSON 数据的顶级或根结构是一个对象。
-
JSON 数据中的根对象包含一个对象数组。
-
对象数组中的每个对象均包含一个
kind
字符串、一个suggestedPrice
字符串和一个available
整数 (没有分数或指数部分的数字)。
借助此模型,您可以调用开发工具包,以便通过读取 GroceryStoreOutputModel[i].kind
、GroceryStoreOutputModel[i].suggestedPrice
和 GroceryStoreOutputModel[i].available
属性来分别检索 kind
、suggestedPrice
和 available
属性值。如果未提供模型,API Gateway 将使用空模型创建默认 UDT。在这种情况下,您将无法使用强类型开发工具包来读取这些属性。
要了解更复杂的映射模板,请参阅以下示例:
要试验 API Gateway 中的映射模板,请按照映射响应负载中的说明操作,具体来说就是步骤 5:设置和测试方法。