

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# AWS AppSync 解析程式映射範本概觀
<a name="resolver-mapping-template-reference-overview"></a>

**注意**  
我們現在主要支援 APPSYNC\$1JS 執行期及其文件。請考慮[在此處](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html)使用 APPSYNC\$1JS 執行期及其指南。

AWS AppSync 可讓您透過對資源執行操作來回應 GraphQL 請求。對於您想要執行查詢或變動的每個 GraphQL 欄位，必須連接解析程式，才能與資料來源通訊。通訊通常是透過資料來源獨有的參數或操作進行。

解析程式是 GraphQL 和資料來源之間的連接器。他們 tell AWS AppSync 如何將傳入的 GraphQL 請求轉譯為後端資料來源的指示，以及如何將來自該資料來源的回應轉譯回 GraphQL 回應。它們是以 [Apache Velocity 範本語言 (VTL)](https://velocity.apache.org/engine/1.7/user-guide.html) 撰寫，會將您的請求視為輸入，並輸出包含解析程式指示的 JSON 文件。您可以將映射範本用於簡單的指示，例如從 GraphQL 欄位傳入引數，或用於更複雜的指示，例如循環使用引數來建置項目，然後再將項目插入 DynamoDB。

解析程式 in AWS AppSync 有兩種類型，會以稍微不同的方式利用映射範本：
+ 單位解析程式
+ 管道解析程式

## 單位解析程式
<a name="unit-resolvers"></a>

單位解析程式是獨立的實體，僅包含請求和回應範本。這種類型可以用於簡易、單一的操作，例如列出來自單一資料來源的清單項目。
+ 請求範本：剖析 GraphQL 操作後接受傳入請求，並將其轉換為所選資料來源操作的請求組態。
+ 回應範本：解譯資料來源的回應，並將其映射至 GraphQL 欄位輸出類型的形狀。

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

管道解析程式包含一個或多個按順序執行的*函數*。每個函數都包含請求範本和回應範本。管道解析程式也具有 *預*範本和 *後*範本，包圍範本包含的函數序列。後續**範本會映射至 GraphQL 欄位輸出類型。管道解析程式與單位解析程式的不同之處在於回應範本映射輸出的方式。管道解析程式可以映射到您想要的任何輸出，包括另一個函數的輸入或管道解析程式的*後續*範本。

 管道解析程式*函數*可讓您撰寫可在結構描述中的多個解析程式之間重複使用的常見邏輯。函數會直接連接到資料來源，就像單位解析程式一樣，包含相同的請求和回應映射範本格式。

下圖示範左側單元解析程式和右側管道解析程式的處理流程。

![\[與單一資料來源通訊的單元解析程式圖表，以及與多個資料來源通訊的管道解析程式圖表。\]](http://docs.aws.amazon.com/zh_tw/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>

管道解析程式的請求映射範本，或 **Before** 步驟，可讓您在執行定義的函數之前執行一些準備邏輯。

#### 函數清單
<a name="functions-list"></a>

管道解析程式將會依序執行的函數清單。管道解析程式要求映射範本評估的結果，會依 `$ctx.prev.result` 提供給第一個函數。每個函數輸出都會依 `$ctx.prev.result` 提供給下一個函數。

#### After 映射範本
<a name="after-mapping-template"></a>

管道解析程式的回應映射範本，或 **After** 步驟，可讓您執行從最後一個函數輸出到預期 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_tw/appsync/latest/devguide/images/PipelineResolver.jpg)


1. 映射範本**前**的管道解析程式

1. 第 1 個函數：函數要求映射範本

1. 第 1 個函數：資料來源呼叫

1. 第 1 個函數：函數回應映射範本

1. 第 2 個函數：函數要求映射範本

1. 第 2 個函數：資料來源呼叫

1. 第 2 個函數：函數回應映射範本

1. 映射範本**之後**的管道解析程式

**注意**  
管道解析程式執行流程為單向，並已在解析程式靜態定義。

#### 實用的 Apache 速度範本語言 (VTL) 公用程式
<a name="useful-apache-velocity-template-language-vtl-utilities"></a>

隨著應用程式複雜性提高，VTL 公用程式和此處的指示詞可加速開發生產力。下列公用程式可在您使用管道解析程式時提供協助。

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

stash 是在每個解析程式和函數映射範本中`Map`提供的 。在單一個解析程式執行期間，則會存在相同的 stash 執行個體。這表示您可以使用 stash 在管道解析程式中的所有要求和回應映射範本、以及全部函數中，傳遞任意資料。停止會公開與 [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>

假設您在名為 的欄位上有 DynamoDB 資料來源和**單位**解析程式`getPost(id:ID!)`，該欄位會傳回具有下列 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>

對於一個字串的對應範本評估。In 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。