

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# AWS AppSync 解析器映射模板概述
<a name="resolver-mapping-template-reference-overview"></a>

**注意**  
我们现在主要支持 APPSYNC\$1JS 运行时系统及其文档。请考虑使用 APPSYNC\$1JS 运行时系统和[此处](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html)的指南。

AWS AppSync 允许您通过对资源执行操作来响应 GraphQL 请求。对于您希望运行查询或变更的每个 GraphQL 字段，必须附加解析器才能与数据来源通信。通常，通信是通过数据来源特有的参数或操作完成的。

解析器是 GraphQL 和数据来源之间的连接器。它们讲述 AWS AppSync 如何将传入的 GraphQL 请求转换为后端数据源的指令，以及如何将来自该数据源的响应转换回 GraphQL 响应。它们是使用 [Apache Velocity 模板语言 (VTL)](https://velocity.apache.org/engine/1.7/user-guide.html) 编写的，该语言将您的请求作为输入，并输出包含解析器指令的 JSON 文档。您可以使用映射模板执行简单的指令（例如，从 GraphQL 字段中传入参数），也可以执行更复杂的指令（例如，循环访问各个参数以构建项目，然后将该项目插入到 DynamoDB 中）。

有两种类型的解析器利用映射模板的方式略有不同： AWS AppSync 
+ 单位解析器
+ 管道解析器

## 单位解析器
<a name="unit-resolvers"></a>

单位解析器是独立的实体，仅包含请求和响应模板。将它们用于简单、单一的操作（例如，列出来自单个数据来源的项目）。
+ 请求模板：在解析 GraphQL 操作后获取传入请求，并将其转换为选定数据来源操作的请求配置。
+ 响应模板：解释来自数据来源的响应，并将其映射到 GraphQL 字段输出类型的形状。

## 管道解析器
<a name="pipeline-resolvers"></a>

管道解析器包含一个或多个按顺序执行的*函数*。每个函数包含一个请求模板和一个响应模板。管道解析器还具有一个*之前* 模板和一个*之后* 模板，它们位于模板包含的一系列函数两侧。*之后* 模板映射到 GraphQL 字段输出类型。管道解析器与单位解析器的不同之处在于响应模板映射输出的方式。管道解析器可以映射到所需的任何输出，包括另一个函数的输入或管道解析器的*之后* 模板。

 管道解析器*函数* 允许您编写可在架构中的多个解析器之间重复使用的通用逻辑。函数直接附加到数据来源，并且像单位解析器一样，包含相同的请求和响应映射模板格式。

下图说明了左侧单位解析器和右侧管道解析器的流程。

![\[与单个数据来源通信的单位解析器的图表以及与多个数据来源通信的管道解析器的图表。\]](http://docs.aws.amazon.com/zh_cn/appsync/latest/devguide/images/unit-pipeline-resolver.png)


管道解析器包含单位解析器支持的功能的超集以及更多功能，但代价是稍微复杂一些。

### 管道解析器剖析
<a name="anatomy-of-a-pipeline-resolver"></a>

管道解析器由**之前**映射模板、**之后**映射模板和一组函数组成。每个函数具有对数据来源执行的**请求**映射模板和**响应**映射模板。由于管道解析器将执行委托给函数列表，因此它不会链接到任何数据来源。单位解析器和函数是对数据来源执行操作的基元。有关更多信息，请参阅[解析器映射模板概述](#aws-appsync-resolver-mapping-template-reference-overview)。

#### 之前映射模板
<a name="before-mapping-template"></a>

管道解析器的请求映射模板或**预备**步骤允许您在执行定义的函数之前执行一些准备逻辑。

#### 函数列表
<a name="functions-list"></a>

管道解析器将按顺序运行的函数的列表。管道解析器请求映射模板评估的结果可供第一个函数用作 `$ctx.prev.result`。每个函数输出可供下一个函数用作 `$ctx.prev.result`。

#### 之后映射模板
<a name="after-mapping-template"></a>

管道解析器的响应映射模板或**后续**步骤允许您执行从最后一个函数的输出到预期 GraphQL 字段类型的一些最终映射逻辑。函数列表中最后一个函数的输出可在管道解析器映射模板中用作 `$ctx.prev.result` 或 `$ctx.result`。

#### 执行流程
<a name="execution-flow"></a>

假定一个管道解析器由两个函数组成，下面的列表表示调用解析器时的执行流程：

![\[GraphQL request flow diagram showing template processing and data source interactions.\]](http://docs.aws.amazon.com/zh_cn/appsync/latest/devguide/images/PipelineResolver.jpg)


1. 管道解析器的**之前**映射模板

1. 函数 1：函数请求映射模板

1. 函数 1：数据来源调用

1. 函数 1：函数响应映射模板

1. 函数 2：函数请求映射模板

1. 函数 2：数据来源调用

1. 函数 2：函数响应映射模板

1. 管道解析器的**之后**映射模板

**注意**  
管道解析器执行流是单向的，并在解析器上静态定义。

#### 非常有用的 Apache Velocity 模板语言 (VTL) 实用程序
<a name="useful-apache-velocity-template-language-vtl-utilities"></a>

随着应用程序复杂性的增加，VTL 实用工具和指令在这里有助于提高开发效率。在使用管道解析器时，以下实用工具可为您提供帮助。

##### \$1ctx.stash
<a name="ctx-stash"></a>

存储区是一个在每个解析器和函数映射模板中提供的`Map`。同一存储实例通过单个解析程序生效。这意味着，您可以使用存储区来跨请求和响应映射模板以及管道解析器中的函数传递任意数据。存储区公开与 [Java 映射](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html)数据结构相同的方法。

##### \$1ctx.prev.result
<a name="ctx-prev-result"></a>

`$ctx.prev.result` 表示在管道解析器中执行的上一个操作的结果。

如果上一个操作是管道解析器的之前映射模板，则 `$ctx.prev.result` 表示模板评估的输出，并提供给管道中的第一个函数。如果上一个操作是第一个函数，则 `$ctx.prev.result` 表示第一个函数的输出，并且可供管道中的第二个函数使用。如果上一个操作是最后一个函数，则 `$ctx.prev.result` 表示最后一个函数的输出，并提供给管道解析器的之后映射模板。

##### \$1return(data: Object)
<a name="return-data-object"></a>

如果您需要从任何映射模板提前返回，`#return(data: Object)` 指令会很有用。`#return(data: Object)` 类似于编程语言中的 *return* 关键字，因为它会从最近的逻辑范围块返回。这意味着在解析器映射模板中使用 `#return` 会从解析器返回。在解析器映射模板中使用 `#return(data: Object)` 会在 GraphQL 字段上设置 `data`。此外，从函数映射模板使用 `#return(data: Object)` 会从函数返回，并继续执行到管道中的下一个函数或解析器响应映射模板。

##### \$1return
<a name="return"></a>

这与 `#return(data: Object)` 相同，但返回 `null`。

##### \$1util.error
<a name="util-error"></a>

`$util.error` 实用工具对于引发字段错误很有用。在函数映射模板中使用 `$util.error` 会立即引发字段错误，从而阻止执行后续函数。有关更多详细信息和其他 `$util.error` 签名，请访问[解析器映射模板实用程序参考](resolver-util-reference.md#aws-appsync-resolver-mapping-template-util-reference)。

##### \$1util.appendError
<a name="util-appenderror"></a>

`$util.appendError` 类似于 `$util.error()`，主要区别在于前者不会中断映射模板的评估。相反，它指示该字段存在错误，但允许评估模板并因此会返回数据。在函数中使用 `$util.appendError` 将不会中断管道的执行流。有关更多详细信息和其他 `$util.error` 签名，请访问[解析器映射模板实用程序参考](resolver-util-reference.md#aws-appsync-resolver-mapping-template-util-reference)。

## 示例 模板
<a name="example-template"></a>

假设您在名为 `getPost(id:ID!)` 的字段上具有 DynamoDB 数据来源和**单位**解析器，该解析器使用以下 GraphQL 查询返回 `Post` 类型：

```
getPost(id:1){
    id
    title
    content
}
```

解析器模板应如下所示：

```
{
    "version" : "2018-05-29",
    "operation" : "GetItem",
    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    }
}
```

这会使用 `id` 输入参数值 `1` 替换 `${ctx.args.id}` 并生成以下 JSON：

```
{
    "version" : "2018-05-29",
    "operation" : "GetItem",
    "key" : {
        "id" : { "S" : "1" }
    }
}
```

AWS AppSync 使用此模板生成有关与 DynamoDB 通信和获取数据（或根据需要执行其他操作）的指令。数据返回后， AWS AppSync 通过可选的可用于执行数据形状塑造或逻辑的响应映射模板以运行数据。例如，在我们从 DynamoDB 中获取结果时，它们可能如下所示：

```
{
        "id" : 1,
        "theTitle" : "AWS AppSync works offline!",
        "theContent-part1" : "It also has realtime functionality",
        "theContent-part2" : "using GraphQL"
}
```

您可以选择使用以下响应映射模板将两个字段联接成单一字段：

```
{
        "id" : $util.toJson($context.data.id),
        "title" : $util.toJson($context.data.theTitle),
        "content" : $util.toJson("${context.data.theContent-part1} ${context.data.theContent-part2}")
}
```

以下是将模板应用到数据后对设置数据形状的方式：

```
{
        "id" : 1,
        "title" : "AWS AppSync works offline!",
        "content" : "It also has realtime functionality using GraphQL"
}
```

此数据作为响应返回给客户端，如下所示：

```
{
        "data": {
                "getPost":      {
                        "id" : 1,
                        "title" : "AWS AppSync works offline!",
                        "content" : "It also has realtime functionality using GraphQL"
                }
        }
}
```

请注意，在大多数情况下，响应映射模板是简单的数据传递，主要由于您返回的是单个项目还是项目列表而不同。对于单个项目，传递：

```
$util.toJson($context.result)
```

对于列表，通常传递的是：

```
$util.toJson($context.result.items)
```

要查看单位解析器和管道解析器的更多示例，请参阅[解析器教程](tutorials.md#aws-appsync-tutorials)。

## 评估的映射模板反序列化规则
<a name="evaluated-mapping-template-deserialization-rules"></a>

映射模板评估结果为字符串。在中 AWS AppSync，输出字符串必须遵循 JSON 结构才有效。

此外，将强制执行以下反序列化规则。

### JSON 对象中不允许使用重复的键
<a name="duplicate-keys-are-not-allowed-in-json-objects"></a>

如果评估得出的映射模板字符串表示 JSON 对象或包含具有重复键的对象，则映射模板会返回以下错误消息：

 `Duplicate field 'aField' detected on Object. Duplicate JSON keys are not allowed.` 

已评估的请求映射模板中的重复键示例：

```
{
    "version": "2018-05-29",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "postId": "1",
        "field": "getPost" ## key 'field' has been redefined
    }
}
```

要修复此错误，请不要重新定义 JSON 对象中的键。

### JSON 对象中不允许使用尾随字符
<a name="trailing-characters-are-not-allowed-in-json-objects"></a>

如果评估得出的映射模板字符串表示 JSON 对象并包含尾随的无关字符，则映射模板会返回以下错误消息：

 `Trailing characters at the end of the JSON string are not allowed.` 

已评估的请求映射模板中的尾随字符示例：

```
{
    "version": "2018-05-29",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "postId": "1",
    }
}extraneouschars
```

要修复该错误，请确保评估的模板的评估结果严格为 JSON。