I need to transform the state machine input for a Task using the keys from one object (which we'll call obj1
) in the input and a separate key-value pair in the input (which we'll call obj2
). Several keys in obj1
are optional parameters so I can't assume the keys that will be present a priori. Additionally, several other key-value pairs may exist that are irrelevant to the Task and so shall not be included in the payload
.
I'm specifically looking for a single Step Functions Task definition that solves this problem.
State machine Task input:
{
"obj1": { "a": 1, "b": "foo" },
"obj2": { "c": 2, "d": "bar" },
"obj3": "baz",
"obj4": { ... }
}
Transformed input for Step Functions Task:
{
"payload": {
"a": 1,
"b": "foo",
"obj2": { "c": 2, "d": "bar" }
}
}
I've been attempting to solve this problem using AWS Step Functions Intrinsic functions to no avail. States.JsonMerge
won't work since I need the key "obj2" to be present in the payload
object, and I don't want irrelevant key-value pairs such as "obj1", "obj3", or "obj4" to be in the payload
. States.Format
seemed promising using the below syntax, but it doesn't appear Amazon States Language (ASL) observes the spread operator. Not sure if it's a syntax issue or if it's simply not possible using ASL.
MyTask:
Type: Task
Resource: arn:aws-us-gov:states:::states:startExecution.sync:2
Parameters:
StateMachineArn: "${my_sfn_arn}"
Input:
payload.$: "States.Format({ ...$.obj1, 'obj2.$': $.obj2 })"
That Task definition failed to deploy with the following error message:
Resource handler returned message: "Invalid State Machine Definition: 'SCHEMA_VALIDATION_FAILED: The value for the field 'payload.$' must be a valid JSONPath or a valid intrinsic function call...
Note: I know this can be accomplished using a Lambda function, but this same problem exists in several Step Functions workflows so my question is only interested in an ASL-native solution for transforming the inputs.
Use the JsonMerge
intrinsic function to "spread" obj1
's keys.
Add a Pass state before MyTask
to isolate obj2
.
"Obj2": {
"Type": "Pass",
"Parameters": { "obj2.$": "$.obj2" },
"Next": "MyTask"
},
Then merge that output with obj1
's keys. We reference obj1
from the execution's $$
Context object:
Input:
payload.$: "States.JsonMerge($, $$.Execution.Input.obj1, false)"
obj1
key can stayInput:
payload.$: "States.JsonMerge($.obj1, $, false)"
Given your input, the task receives the 3 desired keys in the right shape, but keeps a redundant obj1
key:
"payload": {
"a": 1, ✅
"b": "foo", ✅
"obj1": {"a": 1, "b": "foo"},
"obj2": {"c": 2, "d": "bar"} ✅
}