Extract the inner field objects and apply them to respective top level objects using Dataweave2.0 - mule

I am trying to achieve the below output from the given input. I have tried several ways of making a generic function so that when any data is passed with similar structure I get the similar output. Please help me to achieve this.
Input
[{
"name": "Thinker",
"details": [
{
"num": 1
},
{
"num": 2
}
]
},
{
"name": "Blinker",
"details": [
{
"num": 3
},
{
"num": 4
}
]
}]
Output
[{
"name": "Thinker",
"num": 1
},
{
"name": "Thinker",
"num": 2
},
{
"name": "Blinker",
"num": 3
},
{
"name": "Blinker",
"num": 4
}]

The key is mapping through both outer and inner arrays and then flattening the result:
output application/json
---
flatten (payload map ((item, index) -> item.details map ((detail, index) -> {
name: item.name,
num: detail.num
})))

As Aled has mentioned in his comments to one of the answers, this could be another way to solve this.
%dw 2.0
output application/json
---
payload flatMap (item,index) -> (
item.details map {
name: item.name,
num: $.num
}
)

Try this DW
1st Map to Map on main array
2nd Map to Map on details
reduce to convert nested array to single array
%dw 2.0
output application/json
---
payload map(
($.details map(item,index)->{
"name":($.name),
"num":item[0]
})
)reduce($$++$)
Output
[
{
"name": "Thinker",
"num": 1
},
{
"name": "Thinker",
"num": 2
},
{
"name": "Blinker",
"num": 3
},
{
"name": "Blinker",
"num": 4
}
]
DW
%dw 2.0
output application/json
---
payload map(
($.details map(item,index)->{
(keysOf($)[0]):($.name),
(keysOf(item)[0]):item[0]
})
)reduce($$++$)

If your request structure will always remain this way(regardelss of field names), then you can try this script as below, that is more genric and will work on same type of strucure
%dw 2.0
output application/json
---
payload flatMap ((item, index) ->
(item filterObject ($ is Array))[0] map
($ ++ (item filterObject ($ is String | Number | Null)) )
)
Note: it can work on this type of structure always and not depend on field names, and gives expected output
[{
"anyname": "xyz",
"anydetails": [
{
"abc": 1
},
{
"ijk": 2
}
]
}]

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.

How to inherit parent elements for each existing child Mule 4

There is an array of parent elements that you need to duplicate for each child sku element you have.
Input:
{
"items": [
{
"order": "ASD51247",
"reference": "271559410",
"date": "2022-04-01T22:58:19.077Z",
"lines": [
{
"number": "6578523423489",
"description": "ITEM 1"
}
],
"received": "2022-03-31T09:46:13.260Z",
"created": "2022-03-31T09:46:13.109Z"
},{
"order": "AST927353",
"reference": "271944522",
"date": "2022-04-01T22:58:19.038Z",
"lines": [
{
"number": "4563252696546",
"description": "ITEM 2"
},
{
"number": "890456234326",
"description": "ITEM 3"
}
],
"received": "2022-03-31T10:25:08.508Z",
"created": "2022-03-31T10:25:08.353Z"
}
]}
Expected Output:
{ "item":[
{
"order":"ASD51247",
"reference":"271559410",
"date":"2022-04-01T22:58:19.077Z",
"number":"6578523423489",
"description":"ITEM 1",
"receivedAt":"2022-03-31T09:46:13.260Z",
"createdAt":"2022-03-31T09:46:13.109Z"
},
{
"order":"AST927353",
"reference":"271944522",
"date":"2022-04-01T22:58:19.038Z",
"number":"4563252696546",
"description":"ITEM 2",
"received":"2022-03-31T10:25:08.508Z",
"created":"2022-03-31T10:25:08.353Z"
},
{
"order":"AST927353",
"reference":"271944522",
"date":"2022-04-01T22:58:19.038Z",
"number":"890456234326",
"description":"ITEM 3",
"received":"2022-03-31T10:25:08.508Z",
"created":"2022-03-31T10:25:08.353Z"
}]}
In output, must be inherit the parent elements for each child in the "lines" array. Any help would be appreciated. Thank you.
%dw 2.0
output application/json
---
item: payload.items flatMap ((item, index) ->
(item.lines map {
order: item.order,
reference:item.reference,
date: item.date,
number: $.number,
description: $.description,
received: item.received,
created:item.created
})
)
Modifying Imtiyaz's answer a bit
%dw 2.0
output application/json
---
{
items: (payload.items ) flatMap ((item, index) -> (
item.lines map ((line) -> (item - 'lines' - "received" - "created ") ++ {
description: line.description,
number: line.number,
created: item.created,
received: item.received
})
))
}
try below script.
%dw 2.0
output application/json
---
{
items: payload.items flatMap ((item, index) -> (
item.lines map ((line) -> (item - 'lines') ++ {
description: line.description
})
))
}

Transformation of JSON data in mule 4

I have a requirement wherein I have to convert JSON data from one format to other.
I have to fetch corresponding values of JSON array and make them a key value pair.
Below are the required details:
Input:
"Headers": {
"Header": [
{
"Key": "SellerOrganization",
"Value": "XYZ"
},
{
"Key": "SellerType",
"Value": "B2C"
},
{
"Key": "Region",
"Value": "SOUTH"
},
{
"Key": "OrderType",
"Value": "RETURN"
},
{
"Key": "InvoiceType",
"Value": ""
},
{
"Key": "EventType",
"Value": "Created"
},
{
"Key": "EntryType",
"Value": "Call Center"
}
]
}
Expected Output:
{
SellerOrganization:XYZ,
SellerType: B2C,
Region:SOUTH,
OrderType:RETURN,
InvoiceType:"",
EventType:Created,
EntryType:Call Center
}
You can use the dynamic object that it will basically do what you want.
%dw 2.0
output application/json
---
{
(payload.Headers.Header map ((item, index) -> {
(item.Key): item.Value
})
)
}
You can take advantage of reduce function here which will let you convert your array to an key, value pair object
%dw 2.0
output application/json
---
payload.Header reduce ((item, acc = {}) -> acc ++ {
(item.Key): item.Value
})

Merge fields from multiple nested arrays in JSON input into new payload array using Dataweave

I am using Anypoint Studio 7.3 and Mule 4.2.
Using the JSON input below, I would like to create new payloads to write to database tables including a payload which builds a list of customers from each record entry in the array to create a list entry looking like this:
[{
recordId,
customerId
}]
and the same for a list of transactions with each list entry looking like this:
[{
recordId
customerId
transactionId
}]
but when I try to transform the data the field values show either as null or as a list instead of a single field in the object like this:
{
"customers": [{
"record": "1234",
"customerId": [
"5435e1cd-146d-4aac-9164-4a2d80d5eccd"
]
}]
}
instead of this:
{
"customers": [{
"recordId": "1234",
"customerId": "5435e1cd-146d-4aac-9164-4a2d80d5eccd"
}]
}
JSON INPUT:
{
"records": [{
"recordId": "1234",
"customers": [{
"customerId": "1234",
"transactions": [{
"transactionId": "1234",
"prices": [{
"priceId": "1234",
"price": 1.00
}]
}]
}]
}]
}
Thanks for any help
In order to return the list of customers from each record
%dw 2.0
output application/java
---
payload.records flatMap
((record, index) ->
record.customers map ((customer, index) ->
{
recordId: record.recordId,
customerId: customer.customerId
}
)
)
And for returning list of transactions with each list entry
%dw 2.0
output application/json
---
payload.records flatMap
((record, index) ->
record.customers flatMap ((customer, index) ->
customer.transactions map ((transaction, index) ->
{
recordId: record.recordId,
customerId: customer.customerId,
transactionId: transaction.transactionId
}
)
)
)
The key part here is using flatMap for flattening nesting levels of arrays into one.

How can I transform an array of objects to an array of strings and not lose the key in Dataweave?

Hi I need to transform the following JSON object:
{
"products": [
{
"itemno": "123131",
"description" : "Big Widget",
"attributes": [
{
"color": [
{
"value": "Red",
"codeValue": "RED_NO2"
},
{
"value": "Blue Licorice",
"codeValue": "BLUE-355"
}
]
},
{
"chemicals": [
{
"value": "Red Phosphorous",
"codeValue": "RED_PHOS"
},
{
"value": "Chlorine Bleach",
"codeValue": "CHLRN_BLCH"
}
]
}
]
}
]
}
I am trying to transform this with each attribute having an array of values where their value is the codeValue and it's an array of those string values.
This is the desired output:
{
"products": [
{
"itemno": "123131",
"description: : "Big Widget",
"attributes": [
{
"color": ["RED_NO2", "BLUE-355"]
},
{
"chemicals": ["RED_PHOS", "CHLRN_BLCH"]
}
]
}
]
}
This is the Dataweave. I cannot determine how to get the attribute names (i.e. color, chemicals as keys with the desired data.
There is not a lot of good examples on transforming data with Dataweave and I have spent a lot of time trying to figure this out.
This is one of the dataweaves that got there somewhat, but isn't the solution:
%dw 1.0
%output application/json
---
payload.products map
{
"ItemNo" : $.sku,
"Desc" : $.description,
"Test" : "Value",
"Attributes" : $.attributes map
{
'$$' : $ pluck $.value
}
}
Your help is greatly appreciated.
You can do something like this:
%dw 1.0
%output application/json
%function attributeCodeValues(attributes)
attributes map ((attr) ->
attr mapObject ((values, descriptor) ->
{
(descriptor): values map $.codeValue
}
)
)
---
payload.products map {
"ItemNo" : $.sku,
"Desc" : $.description,
"Test" : "Value",
"Attributes" : attributeCodeValues($.attributes)
}