AWS步骤功能和可选参数

时间:2019-11-26 17:07:12

标签: amazon-web-services jsonpath aws-step-functions

我希望将默认值传递给step函数

例如

"Parameters": {
   "foo.$": "$.foo" OR "bar" if "$.foo" not specified
}

是否可以通过JSONPath本机执行此操作,还是必须使用选择+通过状态?

如果在输入中未指定参数时有不中断的方法,我什至会选择使用选择/传递。

如果我在输入中未包含"foo": "",则会收到类似"JSONPath ... could not be found in the input."的错误

5 个答案:

答案 0 :(得分:3)

我正在使用 ChoicePass 状态的组合来解决这个问题。鉴于状态机至少获得一个空的输入对象,您可以使用 IsPresent 状态中的 Choice 比较运算符检查它是否存在成员。如果您的期望变量不存在,您可以路由到 Pass 状态以注入默认回退对象。

示例输入

{
  "keyThatMightNotExist": {
    "options": {
      "foo": "bar",
      "baz": false
    },
    "id": 1234
  }
}

状态机定义

{
  "Comment": "An example for how to deal with empty input and setting defaults.",
  "StartAt": "Choice State: looking for input",
  "States": {
    "Choice State: looking for input": {
      "Type": "Choice",
      "Choices": [
        {

检查是否存在,如果存在,还验证子成员:


          "And": [
            {
              "Variable": "$.keyThatMightNotExist",
              "IsPresent": true
            },
            {
              "Variable": "$.keyThatMightNotExist.id",
              "IsNull": false
            }
          ],

如果键变量存在且其子节点 "id"true,则跳过下一个状态并跳转到 “与 $.keyThatMightNotExist 一起使用的状态”

          "Next": "State that works with $.keyThatMightNotExist"
        }
      ],
      "Default": "LoadDefaults"
    },

以下是我们注入默认值的地方:


    "LoadDefaults": {
      "Type": "Pass",
      "Result": {
        "id": 0,
        "text": "not applicable"
      },
      "ResultPath": "$.keyThatMightNotExist",
      "Next": "State that works with $.keyThatMightNotExist"
    },

此时,有一个对象可以使用。来自实际输入,或使用默认值:


    "State that works with $.keyThatMightNotExist": {
      "Type": "Succeed"
    }
  }
}

enter image description here

有关详细信息,请参阅 AWS Step Functions Developer Guide, choice-state-example

答案 1 :(得分:1)

这可以通过在步函数开始时通过结合"Result""ResultPath"创建通过状态来实现。

  • "Result"的通过状态将是foo的值
  • "ResultPath" : "$.foo"处于通过状态,因此它将在您的通过输入中添加foo变量。

相同的状态定义如下所示:

"Hello": {
      "Type": "Pass",
      "Result": "Added from Hello state",
      "ResultPath":"$.foo",
      "Next": "OtherStates"
    }

一个例子是: 输入到Hello状态

{
 "bar" : "From input" 
}

Hello状态输出

{
 "bar" : "From input",
 "foo" : "Added from Hello state"
}

在这种情况下,它将为foo添加值作为“从Hello状态添加”。因此,为避免由于输入中不存在foo而导致事情中断,您将必须将此“通过状态”定义为要使用该状态的第一个状态或至少一个状态。

P.S。这适用于您仅需如上所述添加单个默认变量的情况。要添加多个默认变量,我建议创建一个Task State并使用lambda函数实现创建默认变量。

答案 2 :(得分:1)

我们有一个类似的问题,该问题的解决方式可能会有所帮助,具体取决于您的SFN任务将要执行的操作。在我们的例子中是Lambda,因此我们可以处理其中的默认行为。

您可以将参数设置为“ $”值,该值将采用提供给SFN的所有输入。

"Parameters": {
      "sfn_input.$": "$"
}

此“ sfn_input”参数现在将向舞台公开,并包含SFN的所有输入。在我们的情况下,我们可以在代码中处理其可选状态。

这显然仅在您的任务可以评估值的存在时才有效。甚至可能在SFN的开头添加了“初始化” Lambda的概念,以专门处理此问题,并添加传递回SFN的默认值。

答案 3 :(得分:0)

我能够通过创建一个cloudwatch规则来解决此问题,该规则每次运行stepfunction时都会插入json。

如果您转到Cloudwatch>创建规则>目标>步进功能>配置输入>常量(JSON文本)

您可以在其中插入默认的json,每次运行stepfunction时都会插入json。

答案 4 :(得分:0)

JSONPath只能查询您的JSON,并且您将无法即时添加数据,默认值将需要出现在输入中。经过多次测试后,我找不到执行此操作的“干净”方法,但这是实现此目的的一些方法。

方法1:

由于您提到过,即使输入中不存在参数,您甚至会想出一种不中断的方法,实际上这很容易做到,但是它不允许我们发送默认值(一个空数组)(如果缺少值)。为此,我们可以通过指定多个子项([''(,'')])来过滤叶节点上的特定值。例如,JSONPath“ $。['Bar','Foo']”将仅过滤出包含节点Bar和Foo的叶节点,但是如果缺少一个或两个都不会返回错误。如果缺少所有指定的子代,它将返回一个空数组[]。这是一个示例状态机来说明这一点。

{
  "StartAt": "ExampleLeafNodes",
  "States": {
    "ExampleLeafNodes": {
      "Type": "Parallel",
      "Branches": [
        {
          "StartAt": "State1-BarPresent",
          "States": {
            "State1-BarPresent": {
              "Type": "Pass",
              "Parameters": {
                "Bar": "Baz"
              },
              "Next": "State2-BarPresent"
            },
            "State2-BarPresent": {
              "Type": "Pass",
              "Parameters": {
                "Foo.$": "$.['Bar','AnyOtherField']"
              },
              "End": true
            }
          }
        },
        {
          "StartAt": "State1-BarNotPresent",
          "States": {
            "State1-BarNotPresent": {
              "Type": "Pass",
              "Parameters": {
                "Field1": "Value1"
              },
              "Next": "State2-BarNotPresent"
            },
            "State2-BarNotPresent": {
              "Type": "Pass",
              "Parameters": {
                "Foo.$": "$.['Bar','AnyOtherField']"
              },
              "End": true
            }
          }
        }
      ],
      "End": true
    }
  }
}

方法2:

取决于您对输入结构的控制程度,如果不需要从输入中引用任何其他变量,则可以使用InputPath和Parameters在单个状态下执行此操作。其背后的想法是将您的输入以以下形式输入州:

"OutputArray": [
  {
    "Bar": {
      "Value": [
        "Baz"
      ]
    }
  },
  {
    "Foo": {
      "Value": [
        "DefaultValueFoo"
      ]
    }
  }
]

数组的第一个元素应该是可能缺少的值,如果缺少该值,则默认值(foo)将是第一个元素。由于第一个元素将始终存在,因此我们可以使用JSONPath“ $ ['OutputArray'] [0] .. Value”获取第一个元素的Value。之后,在Parameters中,我们可以使用JSONPath“ $ [0] [0]”提取确切值。这是此示例的示例状态机:

{
  "StartAt": "State1",
  "States": {
    "State1": {
      "Type": "Pass",
      "Parameters": {
        "OutputArray": [
          {
            "Bar": {
              "Value": [
                "Baz"
              ]
            }
          },
          {
            "Foo": {
              "Value": [
                "DefaultValueFoo"
              ]
            }
          }
        ]
      },
      "Next": "State2"
    },
    "State2": {
      "Type": "Pass",
      "InputPath": "$['OutputArray'][0]..Value",
      "Parameters": {
        "Foo.$": "$[0][0]"
      },
      "End": true
    }
  }
}