Below is the input. There is a parent child-relationship with objects. The "Key"
key specifies that.
For e.g. 109-200C-001
is the child of 109-200C
. There will be n number of objects with different strings.
[
{
"Class": 1,
"Amount": 2,
"Key": "109-200C-001"
},
{
"Class": 3,
"Amount": 4,
"Key": "109-200C"
},
{
"Class": 8,
"Amount": 7,
"Key": "xyz-123-007"
},
{
"Class": 8,
"Amount": 4,
"Key": "xyz-123"
},
]
Need the output as below: Only the parent objects with the Amount of Child and Parent added.
[
{
"Class": 3,
"Amount": 6,
"Key": "109-200C"
},
{
"Class": 8,
"Amount": 11,
"Key": "xyz-123"
}
]
I first remove the child objects, then for each parent I sum the values of all elements that start with the same key. Encapsulating part of the logic in functions make the script very declarative in intent.
%dw 2.0
output application/json
import * from dw::core::Arrays
fun isParent(a, x)=a some ( !($.Key == x.Key) and ($.Key startsWith x.Key))
fun sumChilds(a, x)=a filter ($.Key startsWith x.Key) sumBy $.Amount
---
payload
filter isParent(payload, $)
map {
Class: $.Class,
Ammount: sumChilds(payload, $),
Key: $.Key
}
Output:
[
{
"Class": 3,
"Ammount": 6,
"Key": "109-200C"
},
{
"Class": 8,
"Ammount": 11,
"Key": "xyz-123"
}
]
I could have used the update
operator instead of map()
.
Find below generalized solution that works passing the keys as parameters:
%dw 2.0
output application/json
import * from dw::core::Arrays
fun isParent(a, x, key)=a some ( !($[key] == x[key]) and ($[key] startsWith x[key]))
fun sumChilds(a, x, key, valueKey)=a filter ($[key] startsWith x[key]) sumBy ($[valueKey] as Number)
fun totalizeChilds(a, key, valueKey)=
a
filter isParent(a, $, key)
map ((item, index) -> item update {
case v at ."$(valueKey)" -> sumChilds(payload, item, key, valueKey)
}
)
---
totalizeChilds(payload, "LOCAL_CODE", "AMOUNT")
For your second input you would need to map AMOUNT
to string if you want an exact match.