For each parent item under dataPath, the union_nested_arrays_with_key adapter looks up the object at containerPath, treats each of its child keys as a category, and emits one row per entry found inside each category's array. Each emitted row records its source category name under keyName, and the parent item's other (non-container) fields are preserved on every row. Use mode + keys to whitelist or denylist which categories to include.
Use this when an API returns per-category arrays nested under a single object (for example, one array per channel under a messages object) and you want a single flat report tagged with the category name. Stacking flatten_values once per category instead produces a cartesian product across categories.
| Field | Type | Default | Required | Description |
|---|---|---|---|---|
dataPath |
string | $.* |
Yes | JSONPath to the iterable of parent items. The transformed list is written back under this path. |
containerPath |
string | – | Yes | JSONPath, relative to each parent item, pointing at the container whose children will be unioned. |
keyName |
string | – | Yes | Property name under which each emitted row records its source category key. |
mode |
string | include |
No | One of include or exclude. With include, keys is a whitelist; with exclude, keys is a denylist. |
keys |
array | [] |
No | Category keys to include or exclude depending on mode. May be empty for include (unions every category); must be non-empty for exclude. |
The combinations of mode and keys resolve as follows:
mode |
keys |
Behavior |
|---|---|---|
include |
[] |
Default — union every category in the container. |
include |
non-empty | Whitelist — union only the listed categories. |
exclude |
non-empty | Denylist — union every category except the listed ones. |
exclude |
[] |
Invalid — rejected by the configuration validator. |
Note: Non-list siblings of the container (for example, a scalar or object alongside the per-category arrays) are silently skipped — they do not produce rows and do not raise errors.
Below you can find a before/after example. The original response groups variations per channel:
{
"data": [
{
"time": "2024-01-01T00:00:00Z",
"messages": {
"email": [
{
"variation_name": "v1",
"sent": 100
},
{
"variation_name": "v2",
"sent": 80
}
],
"push": [
{
"variation_name": "v1",
"sent": 50
}
]
}
}
]
}
After the adapter runs, each variation becomes its own row with the channel tagged on it:
{
"data": [
{
"time": "2024-01-01T00:00:00Z",
"channel_type": "email",
"variation_name": "v1",
"sent": 100
},
{
"time": "2024-01-01T00:00:00Z",
"channel_type": "email",
"variation_name": "v2",
"sent": 80
},
{
"time": "2024-01-01T00:00:00Z",
"channel_type": "push",
"variation_name": "v1",
"sent": 50
}
]
}
Configuration:
"response": {
"dataRows": {
"source": "jsonPath",
"value": "$.data.*"
},
"dataAdapters": {
"items": [
{
"type": "union_nested_arrays_with_key",
"config": {
"dataPath": "$.data.*",
"containerPath": "$.messages",
"keyName": "channel_type"
}
}
]
}
}
To include only specific categories, set mode: "include" and list them in keys:
{
"type": "union_nested_arrays_with_key",
"config": {
"dataPath": "$.data.*",
"containerPath": "$.messages",
"mode": "include",
"keys": [
"email",
"push"
],
"keyName": "channel_type"
}
}
To exclude specific categories instead, set mode: "exclude" and list the keys to skip:
{
"type": "union_nested_arrays_with_key",
"config": {
"dataPath": "$.data.*",
"containerPath": "$.messages",
"mode": "exclude",
"keys": [
"summary",
"metadata"
],
"keyName": "channel_type"
}
}
Below you can find example field definitions that read from the transformed structure:
[
{
"id": "time",
"label": "Time",
"dataType": "string.time.date_time",
"value": {
"source": "jsonPath",
"value": "$.time"
}
},
{
"id": "channel_type",
"label": "Channel type",
"dataType": "string.text.value",
"value": {
"source": "jsonPath",
"value": "$.channel_type"
}
},
{
"id": "variation_name",
"label": "Variation name",
"dataType": "string.text.value",
"value": {
"source": "jsonPath",
"value": "$.variation_name"
}
},
{
"id": "sent",
"label": "Sent",
"dataType": "int.number.value",
"value": {
"source": "jsonPath",
"value": "$.sent"
}
}
]