How to create a json message from 2 different json message using Dataweave - mule

I want to create a json message from 2 different Json message. Both input messages are coming from flow variables. How can it be done using Dataweave.
Message 1:
[
{
"userId": 11,
"name": "ABC",
"age": 30
},
{
"userId": 44,
"name": "XYZ",
"age": 30
}
]
Message 2:
[
{
"userId": 11,
"Address": "BLR"
},
{
"userId": 44,
"Address": "CCU"
}
]
Expected output:
[
{
"userId": 11,
"name": "ABC",
"Address": "BLR"
},
{
"userId": 44,
"name": "XYZ",
"Address": "CCU"
}
]
Thank You in advance,
Nitesh

Refer this article. Seems the perfect solution for your usecase.

You can use lookup instead of filter as using filter is performance overhead.
Try this
%dw 1.0
%output application/json
%var adressLookup = {( flowVars.data map {
($.userId ++ "") : $
})}
---
payload map {
userId : $.userId,
name : $.name,
Address : adressLookup[$.userId ++ ""].Address
}
where payload is message1 and flowVars.data is message2
P.S : I have used $.userId ++ "" as key in string format for hashmap, some how numeric key isn't work with weave hashmap.
also refer Merge two json payload with dataweave
Hope this helps.

Related

How to use try function with map in dataweave 2.0

Hi everybody i hope you are well, i have a doubt how can i do to use the try inside map in dataweave, i explain about my issue, i receive a csv file with multiple rows, that rows are group by order first and the second, i use map to transform the data in json ( to join all the rows with the same order) format using a couple colums that colums coming from the csv file, if any colum has empty or null the map fail and broke all the content file, how can i use the try function in dataweave if any group of orders fail only get the order and put in another part of the json and follow with the next order without broke the loop.
Part of the CSV File - Demo:
number,date,upc,quantity,price
1234556,2022-08-04,4015,1,
1234556,2022-08-04,4019,1,2.00
1234556,2022-08-04,4016,1,3.00
1234557,2022-08-04,4015,1,3.00
Dataweave:
%dw 2.0
output application/json
---
payload groupBy ($.number) pluck $ map ( () -> {
"number": $[0].number,
"date": $[0].date,
"items": $ map {
"upc": $.upc,
"price": $.price as Number {format: "##,###.##"} as String {format: "##,###.00"},
"quantity": $.quantity
}
})
Error Message:
Unable to coerce `` as Number using `##,###.##` as format.
NOTE: if put the data in the position "price "= something the the issue are solve in the first row, but i need use the function try or what do you recomend, i cant validate all the elements in csv because this is a demo the complete file has a many columns... if you would has another coment to better my code i'd apreciated.
Expected Result: (I don't know if this is possible)
[
{
"data": [
{
"number":"1234557",
"date":"2022-08-04",
"items":[
{
"upc":"4015",
"price":"3.00",
"quantity":"1"
}
]
}
]
},
{
"Error":[
{
"number":"1234556",
"message":"Unable to coerce `` as Number using `##,###.##` as format."
}
]
}
]
best regards!!
Hi The closer I got from what you asked for was
%dw 2.0
output application/json
import * from dw::Runtime
fun safeMap<T, R>(items: Array<T>, callback: (item:T) -> R ): Array<R | {message: String}> =
items map ((item) -> try(() -> callback(item)) match {
case is {success: false} -> {message: $.error.message as String}
case is {success: true, result: R} -> $.result
})
---
payload
groupBy ($.number)
pluck $
safeMap ((item) -> {
"number": item[0].number,
"date": item[0].date,
"items": item safeMap {
"upc": $.upc,
"price": $.price as Number {format: "##,###.##"} as String {format: "##,###.00"},
"quantity": $.quantity
}
})
This uses a combination of map and try function.
And it outputs
[
{
"number": "1234556",
"date": "2022-08-04",
"items": [
{
"message": "Unable to coerce `` as Number using `##,###.##` as format."
},
{
"upc": "4019",
"price": "2.00",
"quantity": "1"
},
{
"upc": "4016",
"price": "3.00",
"quantity": "1"
}
]
},
{
"number": "1234557",
"date": "2022-08-04",
"items": [
{
"upc": "4015",
"price": "3.00",
"quantity": "1"
}
]
}
]
If you are looking to resolve the value of price if price is null/empty value in the input csv and get rid of the error(which is happening because it cannot format Null values to Number) , try adding default in case of empty/null values and formatting to String only when value exists, like below:
%dw 2.0
output application/json
---
payload groupBy ($.number) pluck $ map ( () -> {
"number": $[0].number,
"date": $[0].date,
"items": $ map {
"upc": $.upc,
"price": ($.price as String {format: "##,###.00"}) default $.price,
"quantity": $.quantity
}
})
Note:
For price, you don't need to convert to Number at all if you want your output as formatted string ultimately.

Nested array data transformation with Mule 3

I am trying to transform data in Mule 3 (DataWeave 1.0) but I am not getting the desire result.
This is the input payload:
[
"https://scrum-caller.com/repo/v1/inside#Changes",
[
{
"id": "8db55441-6255-4d24-8d39-658536985214",
"number": "0w-30",
"Desc": "maintain"
}
],
"https://scrum-caller.com/repo/v1/inside#Changes",
[
{
"id": "11111111-6666-2222-3g3g-854712547412",
"number": "5w-40",
"Desc": "on prod"
}
],
"https://scrum-caller.com/repo/v1/inside#Changes",
[
{
"id": "1ab32c5b-ffs3-3243-74fv-3376218042bb",
"number": "5w-30",
"Desc": "on test"
}
]
]
And my desire output need to be like the one below
{
"#odata.context": "https://scrum-caller.com/repo/v1/inside#Changes",
"value": [
{
"id": "8db55441-6255-4d24-8d39-658536985214",
"number": "0w-30",
"Desc": "maintain"
},
{
"id": "11111111-6666-2222-3g3g-854712547412",
"number": "5w-40",
"Desc": "on prod"
},
{
"id": "1ab32c5b-ffs3-3243-74fv-3376218042bb",
"number": "5w-30",
"Desc": "on test"
}
]
}
Thanks for helping guys.
Assuming all the URLs are the same, since the question doesn't provide details only an example, I just take the first element as the value of the input for "#odata.context", the the value is just filtering out the non-array elements and use the reduce operator to get a single array of the other elements.
%dw 1.0
%output application/json
---
{
"#odata.context" : payload[0],
value : payload filter ($ is :array) reduce ($ ++ $$)
}

Need to convert the payload to the desired output

In the below array there can be multiple objects, and each object can have more than below mentioned key values. I need only the uniqueID and name fields to be displayed.
[
{
"uniqueID": "1",
"Name": "Annie",
"Standard": "3",
"School" : "ABC School"
},
{
"uniqueID": "2",
"Name": "Apoo",
"Standard": "4",
"School" : "PQR School"
},
{
"uniqueID": "3",
"Name": "Xavier",
"Standard": "5",
"School" : "MNO School"
}
]
Desired output:
{
"errors": [
{
"uniqueID": "1",
"Name": "Annie"
},
{
"uniqueID": "2",
"Name": "Apoo"
},
{
"uniqueID": "3",
"Name": "Xavier"
}
]
}
Couple of approaches.
Script
%dw 2.0
output application/json
---
errors: payload map {
uniqueID: $.uniqueID,
Name: $.Name
}
%dw 2.0
output application/json
---
errors: payload map {
($ - "Standard" - "School")
}
In addition to Salim Khan's answer, another way is to use filterObject() to let only the desired attributes in the output. The advantage is that it is somewhat more generic if other attributes are added or changed.
%dw 2.0
output application/json
var allowedKeydNames=["uniqueID", "Name"]
---
{
errors: payload map (
$ filterObject ((value, key, index) -> (allowedKeydNames contains (key as String)))
)
}

How to represent this response using Dataweave?

I have a HTTP requester in my flow which calls AmericanFlightsAPI, its original GET response is like this:
[{
"ID": 1,
"code": "ER38sd",
"price": 400.00,
"departureDate": "2016/03/20",
"origin": "MUA",
"destination": "SFO",
"emptySeats": 0,
"plane": {
"type": "Boeing 737",
"totalSeats": 150
}
I want to filter these records and show only records containing flights having destination "SFO" and "CLE", like this:
{
"flight_ID": 4,
"code": "rree1000",
"destination": {
"destination": "CLE"
}
Other fields for the filtered destination like ID, Code should also be removed from the response.
What is the Dataweave code to achieve this? Actual API is like this: Original API
Quick and easy way could be ..
%dw 2.0
output application/json
---
payload filter ((value, index) -> (value.destination == 'SFO' or value.destination == 'CLE')) map {
"flight_ID" : $.ID,
"code": $.code,
"destination": {
"destination": $.destination
}
}

Define global dataweave function in mule 3

I am defining the global function for payload but in the dataweave 1.0 I am not able to do the task.
I have to define a separate global dataweave file where I have to add the conditions for payload like if gender== "male" then title= "mr."
How can I perform the task. I have added my input and expected payload.
input payload:
{
"persons": [
{
"name": "Devendra",
"gender": "male",
"age": 25
},
{
"name": "aman",
"gender": "male",
"age": 16
}
]
}
expected payload:
{
"persons": [
{
"title": "MR.",
"name": "Devendra",
"gender": "male",
"age": 25,
"adult": true
},
{
"title": "MS.",
"name": "Seema",
"gender": "female",
"age": 16,
"adult": false
}
]
}
In Dataweave 1 you can define a global library by creating a dwl file in src/main/resources like so:
src/main/resources/dw/myFunctions.dwl:
%dw 1.0
%function titleForGender(gender)("mr" when gender=="male" otherwise "whoKnows?")
---
{
"titleForGender": titleForGender
}
This script creates a global function and then exposes it in the body so its available to the other script.
Then in your main dw transformation something like this:
%dw 1.0
%output application/json
%var sampleData={persons:[{name:"Devendra", gender:"male",age:25}, {name:"aman", gender:"male",age:16}]}
%var lib = readUrl("classpath://dw/myfunctions.dwl")
---
persons: sampleData.persons map {
"person": $ ++ {title: lib.titleForGender($.gender)}
}
It uses readUrl to read in the function from the global file as var lib and then uses it when mapping the person data, passing in the gender to the function and getting the title returned from the function.
This outputs:
{
"persons": [
{
"person": {
"name": "Devendra",
"gender": "male",
"age": 25,
"title": "mr"
}
},
{
"person": {
"name": "aman",
"gender": "male",
"age": 16,
"title": "mr"
}
}
]
}