ByteChef LogoByteChef

Expressions

Expressions in ByteChef provide a powerful way to dynamically access, transform, and manipulate data within your workflows. They allow you to reference data from previous steps, perform calculations, implement conditional logic, and create dynamic configurations for your automation processes.

Expression Cheat Sheet

Expressions and types

Formula and text expressions used in ByteChef are primarily written using SpEL (Spring Expression language) with some constraints - simple, yet powerful expression language.

SpEL is based on Java (reference documentation), but no prior Java knowledge is needed to use it.

The easiest way to learn SpEL is looking at examples which are further down this page. Some attention should be paid to data types, described in more detail in the next section.

Data types and structures

The data types used in the execution engine, SpEL expressions and data structures are Java based. These are also the data type names that appear in code completion hints. In most cases ByteChef can automatically convert between Java data types and JSON formats.

Below is the list of the most common data types. In Java types column package names are omitted for brevity, they are usually java.lang (primitives), java.util (List, Map) and java.time

Basic (primitive data types)

Java typeByteChef TypeComment
nullnullable
StringstringUTF-8
Booleanbool
Integerinteger32bit
Longinteger64bit
Floatnumbersingle precision
Doublenumberdouble precision
LocalTimetime
LocalDatedate
LocalDateTimedate-time
UUIDstringuuid

Objects/maps

In ByteChef objects are referred to as Maps;

Arrays/lists

In ByteChef arrays are referred to as Lists; also in some context Collection can be met (it's Java API for handling lists, sets etc.).

Date/Time

See Handling data/time for detailed description of how to deal with date and time in ByteChef.

Expression syntax

Formula expressions

In ByteChef formula expression starts with = and ${} is used to access values.

For example:

=${httpClient_1.body.amount} + 1

will access value defined in httpClient_1.body.amount nested structure and increase it for 1.

Text expressions

Also, it is allowed to write a text expression like

${httpClient_1.body.amount} is total amount

where value defined in httpClient_1.body.amount nested structure will be merged with ' is total amount' literal part.

The same expression can be written as a formula expression:

=${httpClient_1.body.amount} + ' is total amount'

Basics

Most of the literals are similar to JSON ones, in fact in many cases JSON structure is valid SpEL. There are a few notable exceptions:

  • Lists are written using curly braces: {"firstElement", "secondElement"}, as [] is used to access elements in array
  • Strings can be quoted with either ' or "
  • Field names in maps do not to be quoted (e.g. {name: "John"} is valid SpEL, but not valid JSON)
ExpressionResultType
'Hello World'"Hello World"String
truetrueBoolean
nullnullNull
{}an empty listList[Unknown]
{1,2,3,4}a list of integers from 1 to 4List[Integer]
{:}an empty objectMap{}
{john:300, alex:400}a object (name-value collection)Map{alex: Integer(400), john: Integer(300)}
#inputvariable
'AA' + 'BB'"AABB"String

Arithmetic Operators

The +, -, * arithmetic operators work as expected.

OperatorEquivalent symbolic operatorExample expressionResult
div/7 div 23
div/7.0 div 22.3333333333
mod%23 mod 72

Conditional Operators

ExpressionResultType
2 == 2trueBoolean
2 > 1trueBoolean
true AND falsefalseBoolean
true && falsefalseBoolean
true OR falsetrueBoolean
true || falsetrueBoolean
2 > 1 ? 'a' : 'b'"a"String
2 < 1 ? 'a' : 'b'"b"String
nonNullVar == null ? 'Unknown' : 'Success'"Success"String
nullVar == null ? 'Unknown' : 'Success'"Unknown"String
nullVar?:'Unknown'"Unknown"String
'john'?:'Unknown'"john"String

Relational operators

OperatorEquivalent symbolic operatorExample expressionResult
lt<3 lt 5true
gt>4 gt 4false
le<=3 le 5true
ge>=4 ge 4true
eq==3 eq 3true
ne!=4 ne 2true
not!not truefalse

Strings operators

ExpressionResultType
'AA' + 'BB'"AABB"String

Method invocations

As ByteChef uses Java types, some objects are more than data containers - they contain additional methods, but they are not allowed to be called directly on those types.

'someValue'.substring(4) is not allowed expression.

Instead, this is allowed substring('someValue', 4) expression.

ByteChef has built-in functions to help you do various type operations.

Accessing elements of a list or a map

ExpressionResultType
{1,2,3,4}[0]1Integer
{jan:300, alex:400}[alex]a value of field 'alex', which is 400Integer
{jan:300, alex:400}['alex']400Integer
{jan:{age:24}}, alex:{age: 30}}}['alex']['age']30Integer
{foo: 1L, bar: 2L, tar: 3L}.?[#this.key == "foo" OR #this.value > 2L]{'tar': 3, 'foo': 1}Map[String, Long]

Attempting to access non-present elements will cause exceptions. For lists, they are thrown in runtime and for maps they occur before deployment of a scenario during expression validation.

ExpressionError
{1,2,3,4}[4]Runtime error: Index out of bounds
{jan:300, alex:400}['anna']Compilation error: No property 'anna' in map

Filtering lists

Special variable #this is used to operate on single element of list. Filtering all the elements uses a syntax of .?. In addition to filtering all the elements, you can retrieve only the first or the last value. To obtain the first element matching the predicate, the syntax is .^. To obtain the last matching element, the syntax is .$.

ExpressionResultType
{1,2,3,4}.?[#this ge 3]{3, 4}List[Integer]
usersList.?[#this.firstName == 'john']{'john doe'}List[String]
{1,2,3,4}.^[#this ge 3]{3}Integer
{1,2,3,4}.$[#this ge 3]{4}Integer

Transforming lists

Special variable #this is used to operate on single element of list.

For the examples in the table below, let's assume that the listOfPersons contains the following data: {{"name":"Alex", "age": 42}, {"name": "John", "age": 24}} - it is a list of records.

ExpressionResultType
{1,2,3,4}.![#this * 2]{2, 4, 6, 8}List[Integer]
listOfPersons.![#this.name]{'Alex', 'John'}List[String]
listOfPersons.![#this.age]{42, 24}List[Integer]
listOfPersons.![7]{7, 7}List[Integer]
listOfPersons.![{key: #this.name, value: #this.age}]{{"key": "Alex", "value": 42}, {"key": "John", "value": 24}}List[Record]
toMap(listOfPersons.![{key: #this.name, value: #this.age}]){Alex: 42, John: 24}Map[String, Integer]

Note, that toMap() function can be applied to lists of maps, if each map contains two properties: key and value. For other operations on lists, please see the list functions.

Safe navigation

When you access nested structure, you have to take care of null fields, otherwise you'll end up with error. SpEL provides helpful safe navigation operator, it's basically shorthand for conditional operator: someVar?.b means someVar != null ? someVar.b : null

Expression#var valueResultType
var.foo{foo: 5}5Integer
var.foonulljava.lang.NullPointerExceptionjava.lang.NullPointerException
var?.foo{foo: 5}5Integer
var?.foonullnullNull

Invoking static methods

ByteChef does not allow to call static Java methods.

T(java.lang.Math).PI is not allowed expression.

Chaining with dot

ExpressionResultType
{1, 2, 3, 4}.?[#this > 1].![#this > 2 ? #this * 2 : #this]{2, 6, 8}Double

Type conversions

It is possible to convert from a type to another type and this can be done by implicit and explicit conversion. For explicit conversion check functions.

Explicit conversions

Explicit conversions are available as built-in functions.

Implicit conversion

SpEL has many built-in implicit conversions that are available also in ByteChef. Mostly conversions between various numeric types and between String and some useful logical value types. Implicit conversion means that when finding the "input value" of type "input type" (see the table below) in the context where "target type" is expected, ByteChef will try to convert the type of the "input value" to the "target type". This behaviour can be encountered in particular when passing certain values to method parameters (these values can be automatically converted to the desired type).

Some conversion examples:

Input valueInput typeConversion target type
12.34fFloatDouble
42IntegerLong
'Europe/Warsaw'StringZoneId
'+01:00'StringZoneOffset
'09:00'StringLocalTime
'2020-07-01'StringLocalDate
'2020-07-01T'09:00'StringLocalDateTime
'en_GB'StringLocale
'ISO-8859-1'StringCharset
'USD'StringCurrency
'bf3bb3e0-b359-4e18-95dd-1d89c7dc5135'StringUUID

Usage example:

ExpressionInput valueInput typeTarget type
atZone(now(), 'Europe/Warsaw')'Europe/Warsaw'StringZoneId
'' + 42'42'IntegerString

Built-in functions

Type Conversion Functions

FunctionDescription
boolean(value)Converts a value to a boolean.
byte(value)Converts a value to a byte.
char(value)Converts a value to a character.
float(value)Converts a value to a float.
double(value)Converts a value to a double.
int(value)Converts a value to an integer.
long(value)Converts a value to a long.
short(value)Converts a value to a short.

String Functions

FunctionDescription
concat(str1, str2)Concatenates two strings or two lists.
contains(str, substr)Checks if a string contains a substring.
format(formatStr, args...)Formats a string using a format string and arguments (similar to String.format).
indexOf(str, substr)Returns the index of the first occurrence of a substring in a string.
join(list, delimiter)Joins a list of strings with a delimiter.
lastIndexOf(str, substr)Returns the index of the last occurrence of a substring in a string.
length(str)Returns the length of a string.
split(str, delimiter)Splits a string by a delimiter and returns a list of strings.
substring(str, start, end)Returns a substring from start index to end index.

Date and Time Functions

FunctionDescription
atZone(instant, zoneId)Converts an instant to a zoned date-time with the specified time zone.
format(date, [format])Formats a date using the specified format. If no format is provided, uses ISO format.
minusDays(date, days)Subtracts the specified number of days from a date.
minusHours(date, hours)Subtracts the specified number of hours from a date.
minusMicros(date, micros)Subtracts the specified number of microseconds from a date.
minusMillis(date, millis)Subtracts the specified number of milliseconds from a date.
minusMinutes(date, minutes)Subtracts the specified number of minutes from a date.
minusMonths(date, months)Subtracts the specified number of months from a date.
minusSeconds(date, seconds)Subtracts the specified number of seconds from a date.
minusWeeks(date, weeks)Subtracts the specified number of weeks from a date.
minusYears(date, years)Subtracts the specified number of years from a date.
now()Returns the current date and time.
parseDate(dateStr, [format])Parses a string into a date. If no format is provided, uses ISO format.
parseDateTime(dateTimeStr, [format])Parses a string into a date-time. If no format is provided, uses ISO format.
plusDays(date, days)Adds the specified number of days to a date.
plusHours(date, hours)Adds the specified number of hours to a date.
plusMicros(date, micros)Adds the specified number of microseconds to a date.
plusMillis(date, millis)Adds the specified number of milliseconds to a date.
plusMinutes(date, minutes)Adds the specified number of minutes to a date.
plusMonths(date, months)Adds the specified number of months to a date.
plusSeconds(date, seconds)Adds the specified number of seconds to a date.
plusWeeks(date, weeks)Adds the specified number of weeks to a date.
plusYears(date, years)Adds the specified number of years to a date.
timestamp()Returns the current timestamp in milliseconds.

List Functions

FunctionDescription
add(list, element)Adds an element to a list and returns a new list.
addAll(list1, list2)Adds all elements from list2 to list1 and returns a new list.
concat(list1, list2)Concatenates two lists.
flatten(list)Flattens a nested list into a single list.
range(start, end)Creates a list of integers from start to end (inclusive).
remove(list, element)Removes an element from a list and returns the modified list.
set(list, index, element)Sets an element at a specific index in a list and returns the modified list.
size(list)Returns the size of a list or map.
sort(list)Sorts a list in ascending order.

Map Functions

FunctionDescription
put(map, key, value)Adds a key-value pair to a map and returns a new map.
putAll(map1, map2)Adds all key-value pairs from map2 to map1 and returns a new map.
remove(map, key)Removes a key-value pair from a map and returns the modified map.
size(map)Returns the size of a map.
toMap(list)Converts a list of maps with "key" and "value" entries to a single map.

System Functions

FunctionDescription
uuid()Generates a random UUID.