Skip to main content

Expressions

Expressions let you build computed string values by combining references, literal text, and functions.

Basic Syntax

Use the expr keyword to define an expression field:

{
"greeting": {"expr": "Hello ${this.firstName}!"}
}

The ${} placeholders resolve references. Everything outside them is literal text.

Reference Placeholders

Inside ${} you can use any reference type:

{
"users": {
"count": 5,
"item": {
"firstName": {"gen": "name.firstName"},
"lastName": {"gen": "name.lastName"},
"email": {"expr": "${this.firstName}.${this.lastName}@example.com"}
}
}
}

Supported Reference Types

ReferenceExample
Self reference${this.firstName}
Shadow binding${$user.firstName}
Pick reference${admin.name}
Random collection ref${users[*].name}
Indexed collection ref${users[0].name}
note

Expressions resolve references only, not generators. If you need a generated value, assign it to a field first and reference it with this.fieldName.

caution

Conditional references (collection[field=value].field) are not supported inside ${}. If you need to reference a conditionally-filtered item in an expression, bind it to a shadow binding first and reference the binding:

{
"$activeProduct": {"ref": "products[status='active']"},
"label": {"expr": "Featured: ${$activeProduct.name}"}
}

Built-in Functions

Four functions are available out of the box:

lowercase

Converts the entire result to lowercase.

{"expr": "lowercase(${this.firstName}.${this.lastName}@example.com)"}

uppercase

Converts the entire result to uppercase.

{"expr": "uppercase(${this.code})"}

trim

Removes leading and trailing whitespace.

{"expr": "trim(${this.rawInput})"}

substring

Extracts a portion of the string. Takes two extra arguments: start index and end index.

{"expr": "substring(${this.id}, 0, 8)"}

Nesting Functions

Functions can be nested:

{"expr": "uppercase(trim(${this.name}))"}

Examples

Email Generation

{
"users": {
"count": 10,
"item": {
"firstName": {"gen": "name.firstName"},
"lastName": {"gen": "name.lastName"},
"email": {"expr": "lowercase(${this.firstName}.${this.lastName}@company.com)"}
}
}
}

Short ID

{
"items": {
"count": 20,
"item": {
"id": {"gen": "uuid"},
"shortId": {"expr": "uppercase(substring(${this.id}, 0, 8))"}
}
}
}

With Shadow Bindings

{
"users": {
"count": 5,
"item": {
"id": {"gen": "uuid"},
"firstName": {"gen": "name.firstName"},
"lastName": {"gen": "name.lastName"}
}
},
"emails": {
"count": 5,
"item": {
"$user": {"ref": "users[*]"},
"userId": {"ref": "$user.id"},
"email": {"expr": "lowercase(${$user.firstName}.${$user.lastName}@company.com)"}
}
}
}

With Pick References

{
"users": {
"count": 10,
"item": {
"id": {"gen": "uuid"},
"name": {"gen": "name.firstName"}
},
"pick": {"admin": 0}
},
"logs": {
"count": 20,
"item": {
"message": {"expr": "Action performed by ${admin.name}"}
}
}
}

Custom Functions

Register custom expression functions via the Java API:

Generation result = DslDataGenerator.create()
.withSeed(123L)
.withExpressionFunction("slug", (value, args) ->
value.toLowerCase()
.replaceAll("\\s+", "-")
.replaceAll("[^a-z0-9-]", ""))
.fromJsonString(dsl)
.generate();

Then use in DSL:

{
"articles": {
"count": 10,
"item": {
"title": {"gen": "lorem.sentence"},
"slug": {"expr": "slug(${this.title})"}
}
}
}

The ExpressionFunction interface:

@FunctionalInterface
public interface ExpressionFunction {
String apply(String value, List<String> args);
}
  • value — the evaluated first argument of the function call
  • args — any extra arguments (e.g., 0 and 8 in substring(${this.id}, 0, 8))

Limitations

  • expr cannot be combined with gen, ref, or array on the same field
  • Only references are supported inside ${} — not inline generators
  • Conditional references (collection[field=value].field) are not supported inside ${} — use a shadow binding instead
  • Expression results are always strings