

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

# Choice 工作流程状态
<a name="state-choice"></a>

**管理状态和转换数据**  
了解如何[使用变量在状态之间传递数据](workflow-variables.md)和[使用 JSONata 转换数据](transforming-data.md)。

`Choice` 状态 (`"Type": "Choice"`) 向状态机添加条件逻辑。

除了大多数[常用状态字段](statemachine-structure.md#amazon-states-language-common-fields)之外，`Choice` 状态还包含以下额外字段。

**`Choices`（必填）**  
[选项规则](#state-choice-rules)数组，确定状态机接下来转换为什么状态。您必须在 `Choice` 状态中至少定义一条规则。  
运行 `Choice` 状态时，Step Functions 会将每个 **Choice Rule** 评估为 true 或 false。根据评估结果，Step Functions 会转换到工作流中的下一个状态。

**`Default`（可选，建议）**  
如果没有任何 **Choice Rule** 的评估结果为 true，则为要过渡到的状态的名称。

**重要**  
 `Choice` 状态不支持 `End` 字段。此外，它们仅在其 `Next` 字段内部使用 `Choices`。  
当工作流运行时，如果没有任何 **Choice** 表达式的结果为 true，且未提供 **Default** 分支，状态机将因无法从该状态转出而抛出**错误**。**

## Choice Rule（JSONata）
<a name="state-choice-rules"></a>

`Choice` 状态必须有一个值为非空 Choice Rule 数组的 `Choices` 字段，使用 JSONata 时，该数组包含以下字段：
+ **`Condition` 字段** — 计算结果为 true/false 的 JSONata 表达式。
+ **`Next` 字段** — 此字段的值必须与状态机中的状态名称匹配。

以下示例检查数值是否等于 `1`。

```
{
  "Condition": "{% $foo = 1 %}",
  "Next": "NumericMatchState"
}
```

以下示例检查 `type` 变量是否等于 `local`。

```
{
  "Condition": "{% $type = 'local' %}",
  "Next": "StringMatchState"
}
```

以下示例检查字符串是否大于 `MyStringABC`。

```
{
  "Condition": "{% $foo > 'MyStringABC' %}",
  "Next": "StringGreaterMatchState"
}
```

以下示例检查字符串是否为 null。

```
{
 "Condition" : "{% $possiblyNullValue != null and $possiblyNullValue = 42 %}",
 "Next": "NotNullAnd42"
}
```

## Choice Rule（JSONPath）
<a name="state-choice-rules-jsonpath"></a>

`Choice` 状态必须有一个值为非空 Choice Rule 数组的 `Choices` 字段，使用 JSONPath 时，该数组包含以下字段：
+ **比较** – 两个字段，指定要比较的输入变量、比较的类型以及与变量进行比较的值。选项规则支持两个变量之间的比较。在选项规则中，通过在支持的比较运算符名称后附加 `Path`，可以将变量值与状态输入中的另一个值进行比较。比较中的 `Variable` 和路径字段的值必须是有效的[参考路径](amazon-states-language-paths.md#amazon-states-language-reference-paths)。
+ **`Next` 字段** – 此字段的值必须与状态机中的状态名称匹配。

以下示例检查数值是否等于 `1`。

```
{
  "Variable": "$.foo",
  "NumericEquals": 1,
  "Next": "FirstMatchState"
}
```

以下示例检查字符串是否等于 `MyString`。

```
{
  "Variable": "$.foo",
  "StringEquals": "MyString",
  "Next": "FirstMatchState"
}
```

以下示例检查字符串是否大于 `MyStringABC`。

```
{
  "Variable": "$.foo",
  "StringGreaterThan": "MyStringABC",
  "Next": "FirstMatchState"
}
```

以下示例检查字符串是否为空。

```
{
 "Variable": "$.possiblyNullValue",
 "IsNull": true
}
```

以下示例显示了由于前面的 `IsPresent` 选项规则，StringEquals 规则仅 `$.keyThatMightNotExist` 存在时才会被评估。

```
"And": [
 {
 "Variable": "$.keyThatMightNotExist",
 "IsPresent": true
 },
 {
 "Variable": "$.keyThatMightNotExist",
 "StringEquals": "foo"
 }
]
```

以下示例检查带有通配符的模式是否匹配。

```
{
 "Variable": "$.foo",
 "StringMatches": "log-*.txt"
}
```

以下示例检查时间戳是否等于 `2001-01-01T12:00:00Z`。

```
{
  "Variable": "$.foo",
  "TimestampEquals": "2001-01-01T12:00:00Z",
  "Next": "FirstMatchState"
}
```

以下示例将变量与状态输入中的另一个值进行比较。

```
{
 "Variable": "$.foo",
 "StringEqualsPath": "$.bar"
}
```

Step Functions 按照 `Choices` 字段中列出的顺序检查每个选项规则。然后，根据比较运算符确定变量与值匹配的第一条选项规则，并转换为该规则中的 `Next` 字段指定的状态。

支持下列比较运算符：
+ `And`
+ `BooleanEquals`,`BooleanEqualsPath`
+ `IsBoolean`
+ `IsNull`
+ `IsNumeric`
+ `IsPresent`
+ `IsString`
+ `IsTimestamp`
+ `Not`
+ `NumericEquals`,`NumericEqualsPath`
+ `NumericGreaterThan`,`NumericGreaterThanPath`
+ `NumericGreaterThanEquals`,`NumericGreaterThanEqualsPath`
+ `NumericLessThan`,`NumericLessThanPath`
+ `NumericLessThanEquals`,`NumericLessThanEqualsPath`
+ `Or`
+ `StringEquals`,`StringEqualsPath`
+ `StringGreaterThan`,`StringGreaterThanPath`
+ `StringGreaterThanEquals`,`StringGreaterThanEqualsPath`
+ `StringLessThan`,`StringLessThanPath`
+ `StringLessThanEquals`,`StringLessThanEqualsPath`
+ `StringMatches`
+ `TimestampEquals`,`TimestampEqualsPath`
+ `TimestampGreaterThan`,`TimestampGreaterThanPath`
+ `TimestampGreaterThanEquals`,`TimestampGreaterThanEqualsPath`
+ `TimestampLessThan`,`TimestampLessThanPath`
+ `TimestampLessThanEquals`,`TimestampLessThanEqualsPath`

对于每个上述运算符，对应值必须为合适的类型：字符串、数字、布尔值或时间戳。Step Functions 不尝试将数值字段与字符串值匹配。但是，由于时间戳字段在逻辑上是字符串，视为时间戳的字段可能会由 `StringEquals` 运算符匹配。

**注意**  
为了实现互操作性，请不要假定数值比较可用于超出 [IEEE 754-2008 `binary64` 数据类型](https://en.wikipedia.org/wiki/IEEE_754#Basic_and_interchange_formats)所提供量级或精度的值。特别是，超出范围 `[-253+1, 253-1]` 的整数可能会无法按预期方式比较。  
时间戳 (例如，`2016-08-18T17:33:00Z`) 必须遵从 [RFC3339 配置文件 ISO 8601](https://www.ietf.org/rfc/rfc3339.txt)，此外还有更多限制：  
必须使用大写 `T` 分隔日期和时间部分。
大写 `Z` 必须表示没有数字时区偏移。
要了解字符串比较的行为，请参阅 [Java `compareTo` 文档](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#compareTo-java.lang.String-)。  
`And` 和 `Or` 运算符的值必须为非空的选项规则数组，自身不能包含 `Next` 字段。与此类似，`Not` 运算符的值必须为单个选项规则，不能包含 `Next` 字段。  
您可以使用 `And`、`Not` 和 `Or` 创建复杂的嵌套选项规则。但是，`Next` 字段只能显示在顶级选项规则中。  
使用 StringMatches 比较运算符可以对带有一个或多个通配符（“\$1”）的模式进行字符串比较。通配符使用标准的 `\\ (Ex: “\\*”)` 对进行转义。在匹配过程中，除了“\$1”以外，其他字符没有任何特殊含义。