Workflows Improvements: Correct string length and support for objects and arrays in inline variables

The Workflows team has just released two updates to the workflow engine.

Correct string length

Previously, there was an issue in the JSONpath library used by Workflows that always added 2 to the length of a string when using a JSONpath like $.string.length(). This did not affect arrays. A string like “hello” would result in a value of 7 when using the .length() function. This has been fixed in the latest release, and the length function will now return the correct length, which is 5 in the “hello” example.

Please be aware that this change may affect workflows that utilize the .length() function to calculate the length of strings. Please check your workflows for usage of .length() to see if this change will impact you.

Support for objects and arrays in inline variables

Previously, inline variables only supported strings, numbers, and booleans. Inline variables that referenced objects or arrays would output Golang serialization strings, which could cause issues when trying to make HTTP Requests. For example, trying to use $.trigger.identity, which references an identity object, would result in this string.

map[id:ee769173319b41d19ccec6cea52f237b name:john.doe type:IDENTITY]

With the latest release, inline variables now supports JSON serialization of objects and arrays with the use of the .JSON() function. If you need to use an object or an array in an inline variable, and you need it to serialize to JSON, add .JSON() to your JSONpath to force it to serialize to JSON. For example, $.trigger.identity.JSON() produces the following output:

{
    "id": "ee769173319b41d19ccec6cea52f237b",
    "name": "john.doe",
    "type": "IDENTITY"
  }

You do not need to use the .JSON() function to serialize numbers, strings, and integers.

7 Likes

This is a great improvement to what workflows can do!!!

1 Like

This is great, thank you @colin_mckibben !

Trying to get this to work, as I think this might be the solution to a functionality gap workflows has, where we first want to filter an array using JSONpath and then filter by index, as mentioned here:

As test, I have created a workflow, with external trigger, where the only action is to send an email. The email should send the name of the first item whose cost is 10 in the subject. As input to this, I use the example JSON file mentioned here:

So I tried the subject like this:
TEST {{$.trigger.items[?(@.cost == 10)].JSON()[0].name}}
The idea would be to:

  1. Have the original JSON visible in $.trigger
  2. Use the JSONpath .items[?(@.cost == 10)] to filter on items whose cost is 10.
  3. Add .JSON() to your JSONpath to force it to serialize to JSON as you mentioned.
  4. Use the JSONpath [0].name to get the name of the first item.

I expected this result:
TEST apple
However, the results show this:
TEST [map["color":"red" "cost":%!q(float64=10) "name":....., where all items of cost 10 are visible here. Shouldn’t the .JSON() command force this to serialize to JSON?

From what I understand, the .JSON() is only applicable at the end of a JSONpath. You cannot insert it arbitrarily. So this would be the proper way, although this will resolve to a single value so it may still not work.

TEST {{$.trigger.items[?(@.cost == 10)][0].name.JSON()}}

We already saw that {{$.trigger.items[?(@.cost == 10)][0]}} is not returning the desired effect due to how JSONpath works.

I don’t want to insert .JSON() in a JSONpath, I want to perform a JSONpath, add .JSON() to the output of this JSONpath to get a JSON object, and then add a second JSONpath to it. So from my perspective, these are two different JSONpaths, similar to what you can do in coding like this:

$my_number.squared().to_string().concat("1").to_int().squared().to_string()

Here we use the square operation twice, even though it is a string in between.
Similarly I want to take the JSON object that is the input of the workflow, apply a JSONpath to filter out unneeded items, then turn it into a JSON object again using .JSON() and then apply a second JSONpath operation to it, to return the name of the first item.

With general programming this is quite easy, but in this low-code no-code workflows framework, it is quite hard to achieve something as easy as filtering an array and then grabbing the first item. Do you think that the .JSON() keyword can be used here and if so, how?

Ah, that seems more like an enhancement. The .JSON() is a custom function our engineers developed, and is not intended to be chained.

I needed to use this, and couldn’t remember the correct spelling. I first tried with .toJson().
Where is this function documented? I couldn’t find any reference under the Workflows documentation