Dataweave 2 - How can i join 2 arrays by index inside object without lose data parent object - mule

How to join 3 arrays by index (lines, pckSlip and linesDt) and generate an arrays object by linesDt after that you have to generate a new field "totalCost" which is to add the "cost" field of all cost elements in the linesDt array, note the "number" field in the original object is preserved for all new elements spawned from the parent.
Input:
{
"lines":[
{
"requestedQuantity":1,
"pendingQuantity":0
},
{
"requestedQuantity":2,
"pendingQuantity":0
}
],
"number":"98",
"pckSlip":[
{
"trackingNumber":"10534",
"boxesNum":1
},
{
"trackingNumber":"00049",
"boxesNum":1
}
],
"linesDt":[
{
"number":"5678",
"cost":7.7
},
{
"number":"1234",
"cost":7.3
}
]
}
Ouput:
[
{
"number":"5678",
"cost":7.7,
"requestedQuantity":1,
"pendingQuantity":0,
"trackingNumber":"10534",
"boxesNum":1,
"totalCost":15,
"order":"98"
},
{
"number":"1234",
"cost":7.3,
"requestedQuantity":2,
"pendingQuantity":0,
"trackingNumber":"00049",
"boxesNum":1,
"totalCost":15,
"order":"98"
}
]
NOTE: We generate 2 new elements because they are the total of indices found in "linesDt" within an array of elements.
Any help would be appreciated. Thank you.

Mapping each element of lines gives you the index to use in the other arrays. The ++ operator can be used to concatenate objects all the objects together. The calculated fields are added just as another object.
%dw 2.0
output application/json
var totalCost = sum(payload.linesDt.*cost)
---
payload.lines map (
$
++ payload.pckSlip[$$]
++ payload.linesDt[$$]
++ {totalCost: totalCost, order: payload.number}
)
Output:
[
{
"requestedQuantity": 1,
"pendingQuantity": 0,
"trackingNumber": "10534",
"boxesNum": 1,
"number": "5678",
"cost": 7.7,
"totalCost": 15.0,
"order": "98"
},
{
"requestedQuantity": 2,
"pendingQuantity": 0,
"trackingNumber": "00049",
"boxesNum": 1,
"number": "1234",
"cost": 7.3,
"totalCost": 15.0,
"order": "98"
}
]

Assuming that the size of each of the arrays is going to be the same.
Script
%dw 2.0
output application/json
---
1 to sizeOf(payload.lines) map {
(payload.linesDt[($$)] ++ payload.lines[($$)] ++ payload.pckSlip[($$)] ++ ("totalCost": sum(payload.linesDt..cost) as String) ++ ("order": payload.number))
}
Output
[
{
"number": "5678",
"cost": 7.7,
"requestedQuantity": 1,
"pendingQuantity": 0,
"trackingNumber": "10534",
"boxesNum": 1,
"totalCost": "15",
"order": "98"
},
{
"number": "1234",
"cost": 7.3,
"requestedQuantity": 2,
"pendingQuantity": 0,
"trackingNumber": "00049",
"boxesNum": 1,
"totalCost": "15",
"order": "98"
}
]

Related

Mule transform JSON to Map [duplicate]

This question already has answers here:
Convert JSON to Map
(19 answers)
Closed 3 months ago.
I have this JSON object
"actos-evaluacion" : [
{
   "subject" : < id-subject>,
   "name" : < name>,
   "marks" : ["<student_id>:< mark>","< student_id>:< mark>",
     "<student_id>:< mark>"]
},
...
{
   "subject" : < id-subject>,
   "name" : < name>,
   "marks" : ["<student_id>:< mark>","< student_id>:< mark>",
     "<student_id>:< mark>"]
},
]
}
And I want to convert it into this Map, so there will be more Maps than JSON, because each JSON will split into different maps depending on the number of students it has.
{
id_subject :
name :
student_id :
mark :
}
I've tried putting a foreach(json) where subject_id and name where stored in variables. Then set_payload with the list and another foreach for the elements of the list but I don't know how to recover the variables into a Map operator to join them all
A DataWeave script can generate the output. I had to make some assumptions of what the input and output actually look to illustrate the method to loop over the internal array inside each element of the first array. You can adapt the method if the samples are not exactly what you use. My script generates an array of DataWeave objects that are equivalent to a Java Map.
Input:
{
"actos-evaluacion" : [
{
"subject" : "id1",
"name": "name1",
"marks": [ "student1:mark1", "student2:mark2", "student1:mark3"]
},
{
"subject" : "id2",
"name" : "name2",
"marks": [ "student1:mark1", "student2:mark2", "student1:mark3"]
}
]
}
DataWeave script:
%dw 2.0
output application/json
---
payload."actos-evaluacion" flatMap ((item, index) ->
item.marks map ((subject, index2) -> {
id_subject: item.subject,
name: item.name,
student_id: (subject splitBy ":") [0],
mark: (subject splitBy ":")[1]
})
)
Output:
[
{
"id_subject": "id1",
"name": "name1",
"student_id": "student1",
"mark": "mark1"
},
{
"id_subject": "id1",
"name": "name1",
"student_id": "student2",
"mark": "mark2"
},
{
"id_subject": "id1",
"name": "name1",
"student_id": "student1",
"mark": "mark3"
},
{
"id_subject": "id2",
"name": "name2",
"student_id": "student1",
"mark": "mark1"
},
{
"id_subject": "id2",
"name": "name2",
"student_id": "student2",
"mark": "mark2"
},
{
"id_subject": "id2",
"name": "name2",
"student_id": "student1",
"mark": "mark3"
}
]

dataweave - How can i get total of the order Mule 4

I have the following scenario and problem, I recive by CSV File and mapping with DW, groupping by column "PON", i need to get the total of the order multiply this column ( Qty * Price ), I don't have the correct result, I will show you:
CSV Data:
PON,Item,Qty,Price
PON1000,2015,2,38.08
PON1000,2016,1,33.37
PON1001,2015,2,38.08
DW:
%dw 2.0
output application/json
---
payload groupBy ($.PON) pluck $ map ( () -> {
"order": $[0].PON default "",
"total": (sum( $.Price filter ($ != "") ) as Number) as String {format: "##,###.00"},
"products": $ map {
"product": $.Item,
"price": ($.Price as Number) as String {format: "##,###.00"},
"quantity": $.Qty
}
})
Obtained Result:
[
{
"order": "PON1000",
"total": "71.45",
"products": [
{
"product": "2015",
"price": "38.08",
"quantity": "2"
},
{
"product": "2016",
"price": "33.37",
"quantity": "1"
}
]
},
{
"order": "PON1001",
"total": "38.08",
"products": [
{
"product": "2015",
"price": "38.08",
"quantity": "2"
}
]
}
]
I NEED MULTIPLY BY ORDER THE "price" * "quantity" CORRESPONDENT AND FINALLY SUM THAT VALUE AND PUT IN THE COLUMN total by ORDER
Expected Result:
[
{
"order": "PON1000",
"total": "109.53",
"products": [
{
"product": "2015",
"price": "38.08",
"quantity": "2"
},
{
"product": "2016",
"price": "33.37",
"quantity": "1"
}
]
},
{
"order": "PON1001",
"total": "76.16",
"products": [
{
"product": "2015",
"price": "38.08",
"quantity": "2"
}
]
}
]
Any help would be appreciated. Thank you.
Best Regards!!!
I just added two things:
For the total I used Arrays::sumBy which let's you do an operation on each item and the it sums all the results.
I infered from your code you expect the price to be empty, so I created safeNumber() to check that and return 0 in case it's empty (default did not work).
This is the code I've got so far:
%dw 2.0
output application/json
import * from dw::core::Arrays
fun safeNumber(str) = if(isEmpty(str)) 0 else str as Number
---
payload groupBy ($.PON) pluck $ map ( () -> {
"order": $[0].PON default "",
"total": ($ sumBy( (i) -> safeNumber(i.Qty) * safeNumber(i.Price))) as String {format: "##,##0.00"},
"products": $ map {
"product": $.Item,
"price": safeNumber($.Price) as String {format: "##,##0.00"},
"quantity": $.Qty
}
})
Below script will help you.
%dw 2.0
output application/json
import divideBy from dw::core::Objects
---
payload groupBy $.PON mapObject ((value, key, index) ->
({
order: (key),
total: sum(value map ($.Qty * $.Price)),
value : value
})
) divideBy 3
You can use the following DataWeave expression:
%dw 2.0
output application/json
---
payload groupBy $.PON pluck $ map (() -> {
"order": $[0].PON,
"total": sum($ map ($.Qty as Number * $.Price as Number)),
"products": $ map {
"product": $.Item,
"price": $.Price as Number,
"quantity": $.Qty as Number
}
})

How to get a desired output using groupBy in dataweave?

I'm looking for an output similar to this one below where i want to groupBy costomer and orderid.
Input:
[
{
"item": 621,
"orderid": "ON22",
"qty": 45.0,
"customer": "610",
"date": "1988-08-13"
},
{
"item": 63,
"orderid": "ON2234",
"qty": 7,
"customer": "813",
"date": "2001-08-13"
}
]
Desired output:
[
{
"customer":"813",
"data":[
{
"item":63,
"qty":7,
"orderid":"ON2234",
"date":"2001-08-13"
}
]
},
{
"customer":"610",
"data":[
{
"item": 621,
"qty": 45.0,
"orderid": "ON22",
"date": "1988-08-13"
}
]
}
]
You can simply map the default output of your groupBy result since your output does not require any additional logic.
%dw 2.0
output application/json
---
payload groupBy $.customer pluck ((customerOrders, customerId) -> {
customer: customerId as String,
data: customerOrders
})

Compare Object value with array in dataweave?

Sample input 1
{
"data": [
{
"a": [
{
"id": 123
}
],
"a1": [],
"a3": [],
"a4": []
},
{
"b": [
{
"bid": 133
}
],
"b1": [],
"b2": []
},
{
"c": [],
"c1": [],
"d": []
}
]
}
sample input 2: (based on which will filter the sample input 1)
[
"d",
"b",
"b1",
"a4"
]
by comparing the values of both the inputs
Scenario: based on the object names present in 2 input need to filter out the objects from the payload 1.
Expected final output:
{
"data": [{
"a": [{
"id": 123
}],
"a1": [],
"a3": []
},
{
"b2": []
},
{
"c": [],
"c1": []
}]
}
sample code:
%dw 2.0
output application/json
---
payload.data map ((item, index) -> item - "d" - "b" - "b1" - "a4") //
Note: This sample is working but but the values should be taken dynamically from the 2 input
Any help would be appreciated. Thank you.
Try with this:
Payload is the sample input 1 that you have typed in.
%dw 2.0
output application/json
var filterList = [ "d", "b", "b1", "a4" ]
---
data: payload.data map {
($ -- filterList)
}

Postgresql and jsonb - inserting a key/value into a multi-level array

Very similar to this post, but I struggle to adapt from their solution..
My table : public.challenge, column lines JSONB
My initial JSON in lines :
[
{
"line": 1,
"blocs": [
{
"size": 100,
"name": "abc"
},
{
"size": 100,
"name": "def"
},
{
"size": 100,
"name": "ghi"
}
]
},
{
"line": 2,
"blocs": [
{
"size": 100,
"name": "xyz"
}
]
}
]
Desired update :
[
{
"line": 1,
"blocs": [
{
"size": 100,
"name": "abc",
"type": "regular"
},
{
"size": 100,
"name": "def",
"type": "regular"
},
{
"size": 100,
"name": "ghi",
"type": "regular"
}
]
},
{
"line": 2,
"blocs": [
{
"size": 100,
"name": "xyz",
"type": "regular"
}
]
}
]
So basically I need to add the type key+value in every object of blocs, for each element of the root array.
My unsuccessful attempt looks like this :
UPDATE public.challenge SET lines = jsonb_set(lines, '{}', (
SELECT jsonb_set(line, '{blocs}', (
SELECT jsonb_agg( bloc || '{"type":"regular"}' )
FROM jsonb_array_elements(line->'{blocs}') bloc
))
FROM jsonb_array_elements(lines) line
))
;
(currently it sets the whole column as null, maybe due to jsonb_set(lines, '{}' while my json begins as an array ?)
Thanks!
Use jsonb_array_elements to unnest all the array elements and then add the required json and use jsonb_agg to aggregate it again:
with cte as
(select id,
jsonb_agg(jsonb_set(val1,
'{blocs}',
(select jsonb_agg(arr2 || '{"type": "regular"}')
from jsonb_array_elements(arr1.val1 - >
'blocs') arr2)))
from challenge,
jsonb_array_elements(lines) arr1(val1)
group by 1)
update challenge
set lines = (cte.jsonb_agg)
from cte
where challenge.id = cte.id
DEMO