Array Processing with JEXL Script
Overview
The Message Builder policy supports both single-line JEXL expressions and multi-line JEXL scripts. Script mode is activated when the template expression contains var, for, while, or if/else constructs.
Key Differences
| Feature | JEXL Expression | JEXL Script |
|---|---|---|
| Single-line evaluation | ✅ | ✅ |
| Multi-line code | ❌ | ✅ |
for loop | ❌ | ✅ |
var declaration | ❌ | ✅ |
if/else block | ❌ | ✅ |
return statement | ❌ | ✅ |
Example 1: Converting a Tag Array to a JSON Array
Input Body
{
"tags": [
{ "id": 1, "name": "outdoor" },
{ "id": 2, "name": "premium" },
{ "id": 3, "name": "sale" }
]
}
Template (JEXL Script)
#{
var result = '[';
var first = true;
for (tag : body.$.tags) {
if (!first) { result = result + ','; }
result = result + '"' + tag.name + '"';
first = false;
}
result + ']'
}
Body variables extracted via JSONPath are automatically converted to Java List or Map objects, so they support .size() and index access.
Expected Output
["outdoor","premium","sale"]
Example 2: Summing Order Items
Input Body
{
"items": [
{ "name": "Book", "price": 29.99, "quantity": 2 },
{ "name": "Pen", "price": 4.50, "quantity": 5 },
{ "name": "Notebook", "price": 12.00, "quantity": 3 }
]
}
Template (JEXL Script)
#{
var total = 0;
for (item : body.$.items) {
total = total + (item.price * item.quantity);
}
total
}
Expected Output
118.48
Example 3: Conditional Array Filtering
Filter array elements that meet a specific condition and build a new array.
Input Body
{
"products": [
{ "name": "Laptop", "stock": 0 },
{ "name": "Phone", "stock": 15 },
{ "name": "Tablet", "stock": 0 },
{ "name": "Monitor", "stock": 8 }
]
}
Template (JEXL Script)
#{
var result = '[';
var first = true;
for (p : body.$.products) {
if (p.stock > 0) {
if (!first) { result = result + ','; }
result = result + '"' + p.name + '"';
first = false;
}
}
result + ']'
}
Expected Output
["Phone","Monitor"]
Example 4: Role-Based Authorization with if/else
Assign an authorization level based on user roles.
Setup
Assume a custom variable userRoles is already populated (e.g., from the request body) with value ["admin","editor"].
Template (JEXL Script)
#{
var roles = userRoles;
var level = 'NONE';
for (var role : roles) {
if (role == 'admin') {
level = 'FULL';
} else if (role == 'editor' && level != 'FULL') {
level = 'WRITE';
} else if (role == 'viewer' && level == 'NONE') {
level = 'READ';
}
}
level
}
Result
| Roles | authLevel Value |
|---|---|
["admin"] | FULL |
["editor","viewer"] | WRITE |
["viewer"] | READ |
[] | NONE |
Example 5: Accessing Array Elements with $[n] Syntax
To access a specific element of a root-level array, use $[n] syntax.
Input Body (Root Array)
[
{ "id": 1, "name": "First" },
{ "id": 2, "name": "Second" }
]
Variable Reference in Template
#{body.$[0].name}
Output
First
$[0] refers to the first element of the root array. $[1].id would return the id of the second element.
Tips and Common Mistakes
How do I reference body array variables?
Use the standard body.$.path syntax directly inside the JEXL script. For example, for (tag : body.$.tags) iterates over the tags array. JSON array and object values are automatically converted to Java List and Map objects, enabling iteration and property access.
Can I use the `return` keyword?
Yes, in JEXL Script mode you can use return value explicitly. However, returning a value from the last expression (as in examples above) is the recommended approach.
Can I include `{` and `}` inside script templates?
Yes. The Message Builder uses a balanced brace scanner to correctly identify #{} blocks, including those with nested curly braces such as JSON object literals.
Can I use while loops?
Yes, JEXL Script supports while loops as well:
#{
var list = body.$.items;
var i = 0;
var sum = 0;
while (i < list.size()) {
sum = sum + list[i].value;
i = i + 1;
}
sum
}