I need to transform the below JSON
Input :-
{
"type": "donut",
"weight-unit": "lb",
"price-unit": "$/lb",
"price": 10.75,
"batters":
{
"batter":
[
{ "id": "10011", "type": "Original","weight": 500},
{ "id": "10021", "type": "Chocolate","weight": 200, "price": 11.75 },
{ "id": "10031", "type": "Blueberry", "weight": 250, "price": 11.75 },
{ "id": "10041", "type": "Devil's Food", "weight": 150}
]
},
"topping":
[
{ "id": "50011", "type": "None", "price": 0 },
{ "id": "50021", "type": "Glazed", "price": 45.23},
{ "id": "50051", "type": "Sugar", "price": 34.1},
{ "id": "50071", "type": "Powdered Sugar", "price": 21.11},
{ "id": "50061", "type": "Chocolate with Sprinkles", "price": 34.43 },
{ "id": "50031", "type": "Chocolate", "price": 87.40},
{ "id": "50041", "type": "Maple", "price": 64.11}
]
}
The output that I want is
Output :-
{
"type": "donut",
"ChocolateFlavoredGlazedDonut" : {
"weight": 200,
"unit": "kg",
"price": 56.98,
"unit": "$/kg",
},
"ChocolateFlavoredSprinklesDonut" : {
"weight": 200,
"unit": "kg",
"price": 46.18,
"unit": "$/kg",
},
"BlueberryFlavoredSugarDonut" : {
"weight": 250,
"unit": "kg",
"price": 45.85,
"unit": "$/kg",
},
"OriginalGlazedDonut" : {
"weight": 500,
"unit": "kg",
"price": 45.23,
"unit": "$/kg",
},
"OriginalMapleDonut" : {
"weight": 500,
"unit": "kg",
"price": 64.11,
"unit": "$/kg",
},
"OriginalSugarDonut" : {
"weight": 500,
"unit": "kg",
"price": 34.1,
"unit": "$/kg",
},
}
Explanantion:-
"BatterName + ToppingName" : { "weight": 500(batter weight), "unit": "kg"(hard coded), "price": 34.1(batter price + topping price), "unit": "$/kg"(hard coded, }
For example if Batter Name is "Chocolate", then there will be 6 toppings for Chocolate batter and so on for each batter. So total batter number is 4 and topping is 8 , I want 32 items in the final output
You basically need a cross join on toppings and batters. You can use join
from dw::core::Arrays
to do that. It accepts the 2 arrays as input along with two joining criteria (which are inline functions). For that you can just pass a function that always returns true
(or any other static value but it should be same in both criteria functions) so the function will merge every item with every item, and you will get all combos possible.
I noticed that the names of the snack after combining is not very straight forward, so I crated a separated function for that.
%dw 2.0
import join from dw::core::Arrays
import capitalize from dw::core::Strings
output application/json
fun getComboName(batterName, toppingName, snackType) =
capitalize(batterName)
++ (if(lower(batterName) != "original")("Flavoured") else "")
++ (if(lower(toppingName) != "none") capitalize((toppingName splitBy " ")[-1]) else "")
++ capitalize(snackType)
---
join(
payload.batters.batter,
payload.topping,
(a) -> true,
(a) -> true
)
reduce ((combo, acc={"type": payload."type"}) -> {
(acc),
(getComboName(combo.l."type", combo.r."type", payload."type")): {
weight: combo.l.weight,
unit: "kg",
price: (combo.l.price default 0) + (combo.r.price default 0),
unit: "\$/kg"
}
})