ASL Expressions with Step Functions
Tags: stepfunctions, aws, asl
Published: 2020-06-16 18:33:01

[Step Functions](https://aws.amazon.com/step-functions/) are a great tool to coordinate multiple AWS services into serverless workflows. Your workflows can be linear OR conditionals OR parallel OR mapped. Each step can be a different service and inputs are passed from each step to another. More on this can be read [here](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-input-output-filtering.html).
![Which is the odd one out?](https://dev-to-uploads.s3.amazonaws.com/i/nvuwtnot277irjgwn0px.gif)<figcaption>Which is the odd one out?</figcaption>

So, this post is not about how step functions work and what can they do but in this post I would like to focus on how you can pass and process inputs. There are multiple ways to pass inputs between steps and process them before they are passed. By process, I mean validating any primitives OR clean any arrays etc.
![filter it out!!!](https://miro.medium.com/max/400/1*e5GJWv9b_7M8-H08kEBXSQ.jpeg)<figcaption>filter it out!!!</figcaption>

## Table of Contents
* [ASL](#asl)
* [Input Processing](#input-processing)
* [Operations](#operations)

### ASL <a name="asl"></a>
Step functions definition can be defined using [Amazon States Language](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html). More about it can be found [here](https://states-language.net/spec.html). It is a JSON-based structured language which defines various states and tasks performed by those states. An example state machine definition can be:
```json
{
  "Comment": "This is a simple state machine",
  "StartAt": "InitialState",
  "States": {
    "InitialState": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FUNCTION_NAME",
      "Next": "MiddleState"
    },
    "MiddleState": {
      "Type" : "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FUNCTION_NAME2",
      "Next": "EndState"
    },
    "EndState": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FUNCTION_NAME3",
      "End": true
    }
  }
}
```

## Input Processing <a name="input-processing"></a>
Each state can accept InputPath, OutputPath, Parameters and ResultPath parameters. More info on this can be found [here](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-input-output-filtering.html). There are 2 types of input here:
* One which is passed to the state machine. Eg,
```json
{
  "comment": "Input comment.",
  "data": {
    "val1": 23,
    "val2": 17
  }
}
```
* Other which passed to each step. Eg,
```json
"MiddleState": {
  "Type" : "Task",
  "InputPath": "$.data",
  "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FUNCTION_NAME2",
  "Next": "EndState"
}
```
```json
{
  "val1": 23,
  "val2": 17
}
```

In the reminder of the post, we will talk about the 2nd type of input. `$` is a referential operator to refer to original input. `.` allows you to access any property in the input. For eg, `$.data` refers to the `data` property in your input object.

## Operations <a name="operations"></a>
As I mentioned earlier, you can pass inputs to each state in multiple ways. You can pass the output from previous step as input to next. You can skip the output from previous step and pass in the same input as previous step to next step. You can combine the output and input from previous step and then pass it entirely to next step. You can create your own input by picking properties from both input and output from previous step.
![Confused!!!](https://media.giphy.com/media/lffThFKTbC0hpf4KfP/giphy.gif)<figcaption>Confused!!!</figcaption>

Won't go into solving that confusion, it can be read [here](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-input-output-filtering.html).

For the inputs validation or filtering, you can either handle that in your function, pass in the inputs as is and then in your code apply the validations.
![Easy](https://media.giphy.com/media/tfdeUfV3RsVKE/giphy.gif)<figcaption>Easy</figcaption>

But what if I don't want to do this in any function but want to handle it in the step definition itself. Yes, you can do that. ASL spec uses JSONPath to determine the inputs. Using JSONPath, you can accomplish some of the validations or filtering in the definition itself.

### Subset of List
Sample Input
```json
{
  "list": [1, 2, 3, 4, 5]
}
```
`"InputPath": "$.list[1, 2]"`, will result into `[2, 3]` to be passed to the step.

### Nested Property
```json
{
  "person": {
    "name": "it",
    "email": "email",
    "phone": "phone"
  }
}
```
`"InputPath": "$.person.email"`, will result into `"email"` to be passed to the step.

### Nested Property for an item in the list
```json
{
  "persons": [{
    "name": "it1",
    "email": "email1",
    "phone": "phone1"
  }, {
    "name": "it2",
    "email": "email2",
    "phone": "phone2"
  }, {
    "name": "it3",
    "email": "email3",
    "phone": "phone3"
  }]
}
```
`"InputPath": "$.persons[0].email"`, will result into `"email1"` to be passed to the step.
`"InputPath": "$.persons[*].email"`, will result into `["email1", "email2", "email3"]` to be passed to the step.

### Logical Filtering
```json
{
  "scores": [
    {
      "math": 10,
      "english": 20
    },
    {
      "math": 15,
      "english": 20
    },
    {
      "math": 5,
      "english": 20
    },
    null,
    {
      "math": 20,
      "english": 20
    },
    null
  ]
}
```
`"InputPath": "$.scores[(@.math > 10)]"`, will result into `[{ "math": 15, "english": 20 }, { "math": 20, "english": 20 }]` to be passed to the step.
`"InputPath": "$.scores[(@ != null)]"`, will result into the same list without `null`s to be passed to the step.

### Existence Check
```json
{
  "result": {
      "item": 12345,
    }
}
```
`"InputPath": "$.[?(@.result)].result.item"`, will result into `[12345]`. Basically this checks the existence of property in the root object.

These are few of the examples which you can follow. A full list of supported operators can be found [here](https://support.smartbear.com/alertsite/docs/monitors/api/endpoint/jsonpath.html#filters).

![You wish!!!](https://media.giphy.com/media/o5HKScC1PflLO/giphy.gif)<figcaption>You wish!!!</figcaption>