"Transform JSON to JSON with applying groupBy" - mule

I'm transforming payload from json to json with applying groupBy condition but I am not getting proper data what I want.
I have to group the Employee and list his all the tasks.
Currently I am able to apply groupBy employee but his all task is not showing.
payload is:
[
{
"Id": 1,
"EmployeeName": "AA",
"Task": {
"TaskName": "Deploy"
}
},
{
"Id": 1,
"EmployeeName": "AA",
"Task": {
"TaskName": "Test"
}
},
{
"Id": 3,
"EmployeeName": "BB",
"Task": {
"TaskName": "Deploy"
}
}
]
This is my transformation code:
%dw 1.0
%output application/json
---
(payload groupBy ($.EmployeeName ++ $.Id)) map {
EmployeeName : $[0].EmployeeName,
Email : $[0].Email,
Task: $[0].Task
}
This is what I am getting:
[
{
"EmployeeName": "AA",
"Task": {
"TaskName": "Deploy"
}
},
{
"EmployeeName": "BB",
"Task": {
"TaskName": "Deploy"
}
}
]
Expected result:
[
{
"EmployeeName": "AA",
"Task1": {
"TaskName": "Deploy"
},
"Task2": {
"TaskName": "Test"
}
},
{
"EmployeeName": "BB",
"Task1": {
"TaskName": "Deploy"
}
}
]
How can I modify my dataweave to get the expected result.

Following code should work fine.
%dw 1.0
%output application/json
---
payload groupBy ($.Id ++ $.EmployeeName) map {
EmployeeName : $[0].EmployeeName,
({Task : {($.Task map {
('Task' ++ $$ + 1) : $
})}})
}
Hope this helps.

Related

how can I loop through the payload and search within the same payload in another array with similar structure and alter matches

I have entered the payload as shown below, but I have to replace the values ​​of "labelnumber" with the similar number from the main line array with the matches "payload.lines.number = payload.notification.body.lines.number" that are inside the line array inside the notification element, can anyone help me how can we replace it.
input payload
{
"date": "2022-11-15T19:24:36.871Z",
"lines": [
{
"number": "123",
"labelnumber":"ABC",
"received": "2022-11-15T19:30:17.955Z"
},
{
"number": "456",
"labelnumber":"DFG",
"received": "2022-11-15T19:30:57.426Z"
},
{
"number": "789",
"labelnumber":"HIJ",
"received": "2022-11-15T19:31:49.042Z"
}
],
"notification":{
"body":{
"date": "2022-11-15T19:24:36.871Z",
"lines": [
{
"number": "123",
"labelnumber":"",
"received": "2022-11-15T19:30:17.955Z"
},
{
"number": "123",
"labelnumber":"",
"received": "2022-11-15T19:30:57.426Z"
},
{
"number": "456",
"labelnumber":"",
"received": "2022-11-15T19:31:49.042Z"
},
{
"number": "789",
"labelnumber":"",
"received": "2022-11-15T19:31:49.042Z"
},
{
"number": "789",
"labelnumber":"",
"received": "2022-11-15T19:31:49.042Z"
}
]
}
}
}
expected payload
{
"date": "2022-11-15T19:24:36.871Z",
"lines": [
{
"number": "123",
"labelnumber":"ABC",
"received": "2022-11-15T19:30:17.955Z"
},
{
"number": "456",
"labelnumber":"DFG",
"received": "2022-11-15T19:30:57.426Z"
},
{
"number": "789",
"labelnumber":"HIJ",
"received": "2022-11-15T19:31:49.042Z"
}
],
"notification":{
"body":{
"date": "2022-11-15T19:24:36.871Z",
"lines": [
{
"number": "123",
"labelnumber":"ABC",
"received": "2022-11-15T19:30:17.955Z"
},
{
"number": "123",
"labelnumber":"ABC",
"received": "2022-11-15T19:30:57.426Z"
},
{
"number": "456",
"labelnumber":"DFG",
"received": "2022-11-15T19:31:49.042Z"
},
{
"number": "789",
"labelnumber":"HIJ",
"received": "2022-11-15T19:31:49.042Z"
},
{
"number": "789",
"labelnumber":"HIJ",
"received": "2022-11-15T19:31:49.042Z"
}
]
}
}
}
As you can see in this example, I need to loop through the main row array and find the matches within the notification array and assign the corresponding value.
NOTE: maybe in the notification.body has many elements and I don't need to change them and I don't know the name of its elements, in this case it only has "date" but I need to keep them as they are.
With the update operator you can update only the keys that you want. This solution assumes that all the number values are defined in payload.lines.
%dw 2.0
output application/json
---
payload update {
case lines at .notification.body.lines -> lines map ((item, index) ->
item update {
case .labelnumber -> (payload.lines filter ($.number == item.number))[0].labelnumber
}
)
}
Converting reference line Array to Hashmap will help replace values efficiently instead of looping every time. Following code will work
%dw 2.0
output application/json
var lineMap = {(payload.lines map {
($.number) : $.labelnumber
})}
var modifiedLines = (payload.notification.body.lines map ((item, index) -> {
data : item mapObject ((value, key, dataindex) -> {
(key) : if (key ~= 'labelnumber') lineMap[item.number] else value
})
})).data
---
(payload - 'notification') ++
{
"notification":{
"body":{
"lines": modifiedLines
}
}
}
Update : with updated requirement body can have any fields
%dw 2.0
import * from dw::util::Values
output application/json
var lineMap = {(payload.lines map {
($.number) : $.labelnumber
})}
var modifiedLines = payload.notification.body.lines map ((item, index) -> item update 'labelnumber' with lineMap[item.number])
var body = (payload.notification.body - 'lines') ++ {lines : modifiedLines}
---
(payload - 'notification') ++
{
"notification":{
"body": body
}
}

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
})

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"
}
}
]
}

MuleSoft transform gives error while transforming using DWL for JSON payload

Im am new to MuleSoft.I am trying to transform a JSON payload,using transform.
I want to transform my payload as below
Input:
{
"ResponseStatus": {
"Status": "SUCCESS",
"StatusText": "SUCCESS"
},
"Processes": {
"Process": [
{
"ProcessId": "1234567",
"ProcessProperties": {
"Property": [
{
"Name": "XXXXXXXXXXX",
"Value": "11111111",
"Desc": "YYYYYYYY"
},
{
"Name": "AAAAAAAAA",
"Value": "2222222",
"Desc": "BBBBBBBB"
},
{
"Name": "QQQQQQQQQ",
"Value": "#######",
"Desc": "CCCCCCCC"
},
{
"Name": "NNNNNNN",
"Value": "IIIIIIII",
"Desc": "UYUYUYUY"
}
]
},
"EditMode": "CCCCCC",
"ProcessType": "ABCD",
"AppName": "VFVFVGBG",
"StatusHistory": {
"STS": [
{
"Sts": "COMPLETED"
}
]
}
}
]
}
}
Output:
[
{
"ProcessId": "1234567",
"AAAAAAAAA": "2222222",
"QQQQQQQQQ": "#######"
}
]
I have read DWL reference from below Mulesoft link.Also reffered this SO link.
Below is what I have tried so far,
%dw 1.0
%output application/json
---
{
"ProcessId": (payload.Processes.Process.ProcessId)[0],
AAAAAAAAA: {
(payload.Processes.Process.ProcessProperties.Property mapObject {
($.Name):$.Value when $.Name =="AAAAAAAAA" otherwise ""
})
},
QQQQQQQQQ: {
(payload.Processes.Process.ProcessProperties.Property mapObject {
($.Name):$.Value when $.Name =="QQQQQQQQQ" otherwise ""
})
}
}
I am still not able to get the desired output.
It gives me "Cannot coerce a :array to a :key"
Can anyone please help me?
The "property" json element in your input json is "Array",which it is not able to parse to a single value.
Please try below snippet and let me know if that gives your deisred o/p.
payload.Processes.Process map (
(val , index) ->
{"ProcessId":(payload.Processes.Process.ProcessId)[0]
,
(val.ProcessProperties.Property map {
(($.Name) : $.Value) when $.Name =='AAAAAAAAA' }
),
(val.ProcessProperties.Property map {
(($.Name) : $.Value) when $.Name =='QQQQQQQQQ' }
)
}
)

Combine records into a single JSON object per Category using Dataweave

I am using Anypoint Studio 6.1 and Mule 3.8.1 and in Dataweave I have a CSV file as input and JSON list output.
Multiple records are coming in on the CSV file with the same Product Category Id but will have a different product details associated with it. I want my output to be aggregated for each of these records so I have one object for each Product Category Id which contains a list of the product details for each product under that Product Category id. How can I do this?
Current output:
[
{
"Products": {
"ProductDetails": [
{
"ProductDetail": {
"ProductSubDetails": {
"ProductAmount": 7.50,
"ProductReplenFrequency": "monthly",
"ProductsNotes": "Product Notes 1",
"pick": false
},
"ProductType": "PS4 Game"
},
"ProductSubType": "Game"
}
]
},
"ProductsCategoryId": "ProductS001",
"ProductSubType": "Computers and Games"
},
{
"Products": {
"ProductDetails": [
{
"ProductDetail": {
"ProductSubDetails": {
"ProductAmount": 7.50,
"ProductReplenFrequency": "fortnightly",
"ProductsNotes": "Products Notes 2",
"pick": false
},
"ProductType": "X Box One Game"
},
"ProductSubType": "Game"
}
]
},
"ProductsCategoryId": "ProductS001",
"ProductSubType": "Computers and Games"
}
]
Expected output:
[
{
"Products": {
"ProductDetails": [
{
"ProductDetail": {
"ProductSubDetails": {
"ProductAmount": 7.50,
"ProductReplenFrequency": "monthly",
"ProductsNotes": "Product Notes 1",
"pick": false
},
"ProductType": "PS4 Game"
},
"ProductSubType": "Game"
},
{
"ProductDetail": {
"ProductSubDetails": {
"ProductAmount": 7.50,
"ProductReplenFrequency": "fortnightly",
"ProductsNotes": "Products Notes 2",
"pick": false
},
"ProductType": "X Box One Game"
},
"ProductSubType": "Game"
}
]
},
"ProductsIdentifier": "ProductS001",
"ProductSubType": "Computers and Games"
}
]
Dataweave code:
%dw 1.0
%input payload application/csv
%output application/json skipNullOn = "everywhere" , encoding = "UTF-8"
%var dataLookup = {(payload."ProductsCategoryId" map {($.Id): $.Value})}
---
(payload filter $$ > 2) map ((payload01 , indexOfPayload01) -> {
Products: {
ProductsDetails: [{
ProductsDetail: {
ProductsubDetails: {
ProductsAmount: payload01."Products Amount" as :number,
ProductsFrequency: payload01."Products Frequency"
},
ProductsType: payload01."Products Type"
}
}]
},
ProductsCategoryId: payload01."ProductsCategoryId"
})
Sample Data:
ProductsCategoryId,Product Type,Product Frequency,Product Amount
ProductS001,PS4 Game,Monthly,7.5
ProductS001,X Box One Game,Fortnightly,7.5
ProductS002,Lego,Daily,7
Thanks
You have to use look up for achieving desired output. Please refer the following answer for more details
Lookup list of Maps variable in data weave script
Updated answer as per comments
Try with following mapping. Also I am not sure why you have use filter $$ > 2.
For body starts at line 5 you can add input reader property "bodyStartLineNumber" Please refer link for more details
%dw 1.0
%input payload application/csv
%output application/json skipNullOn = "everywhere" , encoding = "UTF-8"
---
payload groupBy $.ProductsCategoryId map {
Products: {
ProductsDetails: $ map (product , indexOfProduct) -> {
ProductsDetail: {
ProductsubDetails: {
ProductsAmount: product."Product Amount" as :number,
ProductsFrequency: product."Product Frequency"
},
ProductsType: product."Product Type"
}
}
},
ProductsCategoryId: $."ProductsCategoryId"[0]
}
Output gnerated:-
[
{
"Products": {
"ProductsDetails": [
{
"ProductsDetail": {
"ProductsubDetails": {
"ProductsAmount": 7
},
"ProductsType": "Lego"
}
}
]
},
"ProductsCategoryId": "ProductS002"
},
{
"Products": {
"ProductsDetails": [
{
"ProductsDetail": {
"ProductsubDetails": {
"ProductsAmount": 7.5
},
"ProductsType": "PS4 Game"
}
},
{
"ProductsDetail": {
"ProductsubDetails": {
"ProductsAmount": 7.5
},
"ProductsType": "X Box One Game"
}
}
]
},
"ProductsCategoryId": "ProductS001"
}
]
HTH