输入和输出
概述
工作流开始运行时,会接收用户指定的输入数据,并将数据传递至工作流的开始节点,即 start 所指向的节点。在后续的执行中,每个节点都接收上一个节点的输出作为自己的输入,并在执行结束后,继续将自己的输出传给下一个节点。所有的输入输出数据均为 JSON 格式。本节将为您介绍如何处理节点的输入输出数据。
工作流的输入与输出
- workflow 的输入由用户提供,如果用户未提供输入,那么使用 "{}" 作为默认输入。
- workflow 的输出是最后一个节点的输出。
节点的输入与输出
workflow 的输入作为 start 节点的输入,当一个节点执行结束后,它的输出会成为下一个节点的输入。
节点可以通过 stateDataFilter 处理上一个节点传入的输入数据,和传给下一个节点的输出数据。operation 节点还可以通过 actionDataFilter 定义调用云函数时的输入,和处理云函数的返回结果,比如把节点输入数据的其中一部分作为 payload 去调用云函数,云函数返回结果后只取出其中的一部分放入节点数据里。
stateDataFilter 和 actionDataFilter 都是节点的可选参数,节点若不定义则不对输入输出做其它处理。

stateDataFilter
| 参数 | 类型 | 描述 |
|---|---|---|
| input(可选) | string | jq 表达式,在执行 state 前过滤输入 |
| output(可选) | string | jq 表达式,在 state 结束前过滤输出 |
示例:
工作流的定义如下:
1name: demo
2start: hello
3description: "从输入数据中取出 apple 对应的值"
4states:
5 - type: wait
6 name: hello
7 stateDataFilter:
8 input: ".fruits"
9 output: "{res: .apple}"
10 seconds: 2
11 end: true
假定工作流的输入数据为:
1{
2 "fruits": {
3 "apple": 7,
4 "banana": 10
5 },
6 "vegetables": ["potato", "tomato", "carrot"]
7}
工作流的处理流程如下:
- 收到执行请求和输入数据,找到开始节点
hello,将数据传递给hello。 -
hello根据stateDataFilter的input参数处理输入数据,处理结果作为节点数据,结果为:JSON1{ 2 "apple": 7, 3 "banana": 10 4} hello节点执行wait逻辑,等待 2 秒。-
hello节点操作结束,根据stateDataFilter的output参数处理输出数据,结果为:JSON1{ 2 "res": 7 3} - 由于
hello节点之后没有其他节点,因此hello执行结束后整个工作流也随之结束,工作流的输出即上一步中的结果。
实际验证中,stateDataFilter.input: ".fruits" 的输出结果为 {"apple":7,"banana":10},stateDataFilter.output: "{res: .apple}" 的输出结果为 {"res":7}。如果通过执行历史查看节点输入,StateWaitEntered.eventDetail.input 仍显示原始工作流输入;验证 input 过滤效果时,应以节点退出结果或最终执行输出为准。
actionDataFilter
在 operation 节点中调用函数计算等公有云服务时,可以通过这个 filter 定义传给云服务的参数,也能对服务返回的结果进一步提取、筛选,并加入到节点数据中。
| 参数 | 类型 | 描述 |
|---|---|---|
| fromStateData(可选) | string | jq 表达式,从节点数据中过滤部分数据传给云服务 |
| results(可选) | string | jq 表达式,对调用云服务返回的结果进一步过滤,筛选出想要的数据 |
| toStateData(可选) | string | jq 表达式,把 results 的结果添加或合并到 state data 的某个字段内;若未指定,则放入节点数据的顶层 |
| useResults(可选) | bool | 是否把云服务返回的结果放入节点数据中,默认为 true |
示例:
1name: demo
2start: hello
3description: "从输入数据中取出 apple 对应的值"
4states:
5 - type: operation
6 name: hello
7 actionDataFilter:
8 fromStateData: "{ stateInput: .hello }"
9 results: "[ .breads[0], .pasta[1] ]"
10 toStateData: ".itemsToBuyAtStore"
11 resource: "brn:cfc:bj:123456:function:test:$LATEST"
12 end: true
假定本次工作流的输入为 {"hello":"world"},函数的返回为:
1{
2 "breads": ["baguette", "brioche", "rye"],
3 "pasta": ["penne", "spaghetti", "ravioli"]
4}
那么工作流的处理流程大致如下:
- 收到执行请求和输入数据,找到开始节点
hello,将输入数据{"hello":"world"}传递给hello。 hello节点内没有定义stateDataFilter,因此不执行输入预处理。hello节点内定义了actionDataFilter,根据fromStateData参数执行数据处理,得到{"stateInput": "world"}。hello节点将上一步得到的结果作为payload去调用函数。- 函数返回结果后,根据
actionDataFilter的results参数处理函数返回,结果为["baguette", "spaghetti"]。 -
根据
actionDataFilter的toStateData参数继续处理,把results的结果放到节点数据的itemsToBuyAtStore字段中。若该字段不存在,则自动创建。最终节点数据为:JSON1{ 2 "hello": "world", 3 "itemsToBuyAtStore": ["baguette", "spaghetti"] 4} hello节点内没有定义stateDataFilter,因此不执行输出预处理,工作流执行结束。
jq 表达式
从上文的介绍中可知,节点数据的过滤、处理都依靠 jq 表达式,这里展示出常用的 jq 操作。源数据如下:
1{
2 "store": {
3 "book": [
4 {
5 "category": "reference",
6 "author": "Nigel Rees",
7 "title": "Sayings of the Century",
8 "price": 8.95
9 },
10 {
11 "category": "fiction",
12 "author": "Evelyn Waugh",
13 "title": "Sword of Honour",
14 "price": 12.99
15 },
16 {
17 "category": "fiction",
18 "author": "Herman Melville",
19 "title": "Moby Dick",
20 "isbn": "0-553-21311-3",
21 "price": 8.99
22 },
23 {
24 "category": "fiction",
25 "author": "J. R. R. Tolkien",
26 "title": "The Lord of the Rings",
27 "isbn": "0-395-19395-8",
28 "price": 22.99
29 }
30 ],
31 "bicycle": {
32 "color": "red",
33 "price": 19.95
34 }
35 }
36}
各类操作结果如下:
| 表达式 | 结果 |
|---|---|
| .store | store 内的所有数据 |
| .store.bicycle.price | store 内 bicycle 的价格 |
| {color: .store.bicycle.color} | {"color": "red"} |
| .store.book[2] | store 内的第3个book对象 |
| .store.book[0:2] | store 内的前两本书 |
| .store.book[] | select(.price < 10) | store 内所有价格小于10的book |
| .store.book[].author | store 内的所有书的作者 |
jq 是一个功能强大的、用于解析 json 数据的工具,关于 jq 的更多用法,您可参考
评价此篇文章
