Activity Input and Output
Overview
Every activity in a process (e.g., User Task, Service Task, Script Task) can receive data (input) and return data (output). The definition of input and output controls which data an activity processes and which results it returns to the process.
Summary
Input parameters define which data an activity receives. Output parameters define which results flow back into the process. JSONata is used for transforming data between activities – an elegant query language for JSON data.
Why this is helpful
Through targeted control of input and output, processes remain clear, activities receive only the required data, and results are returned in a clean structure.
Core Concept
Input Parameters
The input parameter defines which data an activity receives. This can be:
- Individual fields from process data
- Entire objects or arrays
- Transformed data using JSONata
- Calculated values
Example: An activity needs only the invoice number and recipient:
{
"invoice_number": $.invoice.number,
"recipient": $.invoice.recipient.name
}
Output Parameters
The output parameter transforms the raw result of an activity into a structured format. It determines which data is extracted from the result and how it is prepared.
Interaction with Result Path
The output parameter transforms the data (WHAT), the result path determines where it is stored (WHERE).
Example: The result of a calculation is structured:
{ "calculated_value": $.result, "timestamp": $.date }
JSONata – Data Transformation
JSONata is a powerful query language for transforming, filtering, and reshaping JSON data. It allows flexible adaptation of data between activities.
Basic Syntax
| Syntax | Description | Example |
|---|---|---|
$.property |
Access a field | $.customer.name |
items[$.price>100] |
Filter array | Only items with price > 100 |
{ "key": $.value } |
Create new object | Object with transformed values |
$sum(array) |
Sum array | Sum of all values |
$now() |
Current timestamp | Today's date/time |
Important Functions
$sum(array)– Sums numeric values$filter(array, function)– Filters array by condition$map(array, function)– Transforms each element$now()– Current timestamp$substring(text, start, length)– Extract substring$split(text, separator)– Split text
Try JSONata
Pantarey JSONata Editor: In the Process Designer it is possible to test expressions directly and see the result live.
Alternatively, the official JSONata Playground: try.jsonata.org
Usage in Pantarey
In the Process Designer
- Open Process Designer
- Select an activity (e.g., Service Task)
- Find the "Input Parameter" and "Output Parameter" fields in Properties
- Enter JSONata expression
- Save and deploy process
Typical Scenarios
| Scenario | Input Parameter | Output Parameter |
|---|---|---|
| Pass entire data structure | $ |
result |
| Only specific fields | { "id": $.order_id } |
order_status |
| Calculated result | { "total": $sum($.items.price) } |
calculated_total |
| Transformation | $.items[price > 100] |
filtered_items |
Best Practices
Input Parameters
- ✅ Pass only the actually required data
- ✅ Use descriptive field names
- ✅ Transform data directly in input, rather than in the activity
- ❌ Avoid passing the entire process variable (
$) when only individual fields are needed
Output Parameters
- ✅ Define a clear output path (e.g.,
result.customer_data) - ✅ Structure results sensibly
- ✅ Avoid overwriting important process data
- ❌ Don't use generic names like
dataoroutput
JSONata Expressions
- ✅ Test expressions in the Pantarey JSONata Editor (available in Process Designer)
- ✅ Alternatively: try.jsonata.org
- ✅ Keep expressions clear and readable
- ✅ Comment complex logic
- ❌ Avoid nested expressions that are difficult to debug
Practical Examples
Modify single attribute
Extract the order object and set the status to completed.
Input:
{
"order": {
"id": "ORD-1001",
"status": "open",
"total": 249.99
}
}
JSONata Expression:
$.order ~> | $ | { "status": "completed" } |
Output:
{
"id": "ORD-1001",
"status": "completed",
"total": 249.99
}
Calculate age in years
Calculate age in years from the date of birth.
Input:
{
"birthday": "1991-03-06"
}
JSONata Expression:
(
$now := $toMillis($now());
$birthMillis := $toMillis(birthday & "T12:00:00Z");
$years := $floor(($now - $birthMillis) / (365.25 * 24 * 60 * 60 * 1000));
$years
)
Output:
34
Determine first and last day of previous month
Calculate the start and end date of the previous month as ISO date.
JSONata Expression:
(
$firstThisMonthMs := $toMillis($substring($now(), 0, 7) & "-01T00:00:00Z");
$lastPrevISO := $fromMillis($firstThisMonthMs - 1);
{
"firstDayPrevMonth": $substring($lastPrevISO, 0, 7) & "-01",
"lastDayPrevMonth": $substring($lastPrevISO, 0, 10)
}
)
Output:
{
"firstDayPrevMonth": "2025-12-01",
"lastDayPrevMonth": "2025-12-31"
}
Add attribute to each array object
Extends each element of an array with an additional field additionalAttr.
Input:
{
"array": [
{"existingAttr": "1"},
{"existingAttr": "2"}
]
}
JSONata Expression:
$.array.$merge([$, {"additionalAttr": "Hello"}])
Output:
[
{
"existingAttr": "1",
"additionalAttr": "Hello"
},
{
"existingAttr": "2",
"additionalAttr": "Hello"
}
]
Find common elements of two arrays
Returns all values that are present in both array array and array compareArray.
Input:
{
"array": [1, 2, 5, 6],
"compareArray": [1, 2, 3]
}
JSONata Expression:
[$filter($.array, function($v, $i, $a) {
$exists($$.compareArray[$v = $])
})]
Output:
[1, 2]
Generate array from number range
Creates an array of objects with sequential values between start and end.
Input:
{
"start": 1,
"end": 3
}
JSONata Expression:
[$map([($$.start)..($$.end)], function($v) {
{
"value": $v
}
})]
Output:
[
{ "value": 1 },
{ "value": 2 },
{ "value": 3 }
]
Generate dynamic SQL for vacation overlaps
Generates an SQL statement that creates a CASE WHEN query for each day in a period around the requested vacation. This allows checking for vacation overlaps with existing requests.
Input:
{
"vacation_from": "2025-12-12",
"vacation_to": "2025-12-14"
}
JSONata Expression:
``` ( $oneDay := 86400000;
$startDate := $toMillis(vacation_from) - (4 * $oneDay); $endDate := $toMillis(vacation_to) + (4 * $oneDay);
$days := $map( $spread([0..$floor(($endDate - $startDate) / $oneDay)]), function($i) { $fromMillis($startDate + ($i * $oneDay), "[Y0001]-[M01]-[D01]") } );
$cases := $map( $days, function($day) { "CASE WHEN DATE '" & $day & "' BETWEEN vacation_from AND vacation_to THEN 'X' ELSE '' END AS \"" & $day & "\"" } );
"SELECT p.document_name AS applicant, " & $join($cases, ", ") & " FROM vacation_request_only u JOIN person p ON u.applicant = p.id" & " WHERE vacation_from <= DATE '" & vacation_to & "' AND vacation_to >= DATE '" & vacation_from & "'" & " ORDER BY p.document_name" ) ```
Output:
sql
SELECT p.document_name AS applicant,
CASE WHEN DATE '2025-12-08' BETWEEN vacation_from AND vacation_to THEN 'X' ELSE '' END AS "2025-12-08",
CASE WHEN DATE '2025-12-09' BETWEEN vacation_from AND vacation_to THEN 'X' ELSE '' END AS "2025-12-09",
...
FROM vacation_request_only u
JOIN person p ON u.applicant = p.id
WHERE vacation_from <= DATE '2025-12-14'
AND vacation_to >= DATE '2025-12-12'
ORDER BY p.document_name
Troubleshooting
Expression is not executed
Cause: Syntax error in the JSONata expression
Solution:
- Test the expression in the Pantarey JSONata Editor (in Process Designer)
- Alternatively: try.jsonata.org
- Check for missing brackets or commas
- Ensure correct path specifications (e.g.,
$.customer.name)
Result is empty or undefined
Cause: The specified path does not exist in the process data
Solution:
- Check the process data in the Process Explorer
- Use
$exists($.field)to test if a field exists - Use fallback values:
$.field ? $.field : "default"
Output is not saved in process variable
Cause: Result path is empty or incorrectly defined
Solution:
- Ensure the result path contains a valid path
- Use meaningful names (e.g.,
result.customer_data) - More information: Result Path
- Redeploy the process
FAQ – Frequently Asked Questions about Input/Output
Do I always have to use JSONata?
Yes, but JSONata can be very simple. A simple field reference like $.order_id or a simple JSON object { "id": $.order_id } is already valid JSONata. Complex transformations with functions like $map() or $filter() are only used when needed.
Can I return multiple fields in the output?
Yes. Use an object as output:
{
"status": $.status,
"total": $.total
}
How do I access nested objects?
With dot notation: $.customer.address.city
Can I transform arrays?
Yes, with $map(): $map($.items, function($item) { $item.price * 1.19 })
More on array processing in the JSONata Documentation on Arrays.
What is the difference between Input Parameter, Output Parameter, and Result Path?
- Input Parameter: Which data goes into the activity (source)
- Output Parameter: How the result is transformed (WHAT)
- Result Path: Where the transformed result is stored (WHERE)
More on this: Result Path
Can input expressions access previous task results?
Yes, via the process variables. If Task A has stored its result under resultA, Task B can access it with $.resultA.
Further Information
JSONata Documentation
- Pantarey JSONata Editor – Integrated in the Process Designer for live testing
- Official JSONata Documentation
- JSONata Playground
- JSONata Exerciser
Related Topics
- Template Functions for text transformations
- Predefined Services with preconfigured inputs
- Script Tasks for complex logic
Next Steps
- Learn more about Creating Processes
- Use Service Tasks with Input/Output
- Perform Process Deployment