Mule DWL - Flatten json hierarchical elements - mule

I have json payload as below:
Attributes:{
Contact:{
Address:{
PersonName:"John",
Line1:"sdsds",
Line2:"sdsdsd",
SubAddress:{
PersonName:"John",
Line1:"ggghg",
Line2:"xzxzxzx"
}
},
Phone:{
Home:"2323232323",
Office:"4545454545"
}
},
Id:"2343434",
order:"3343434"
}
I want to flatten the hierarchy to below output
Attributes:{
Contact.Address.PersonName:"John",
Contact.Address.Line1:"sdsds",
Contact.Address.Line2:"sdsdsd",
Contact.Address.SubAddress.PersonName:"John",
Contact.Address.SubAddress.Line1:"ggghg",
Contact.Address.SubAddress.Line2:"xzxzxzx",
Contact.Phone.Home:"2323232323",
Contact.Phone.Office:"4545454545",
Id:"2343434",
order:"3343434"
}
Attributes element can have any number of complex elements like the "Address" and "Contact". We will not know the key value of the complex elements at the point of coding. DWL should be able to produce a single level output. Want generic solution for this flattening using dw1 in Mule 3. Please help.

Below scripts recursively goes over the payload and construct single key-valued
pair object
%dw 1.0
%output application/json
%var payload = {"Attributes":{"Contact":{"Address":{"SubAddress":[{"PersonName1":"John","Line1":"ggghg","Line2":"xzxzxzx"},{"PersonName":"Jar","Line1":"ggghg","Line2":"xzxzxzx"}]},"Phone":{"Home":"2323232323","Office":"4545454545"}},"Id":"2343434","order":"3343434"}}
%function constructKeys(oldKeys, newKey) oldKeys ++ '.' ++ newKey
%function writeData(json ,output, keys) json match {
case is :null -> null,
case is :array -> {(json map ((item, index) -> writeData(item, output, keys ++ index)))},
case is :object -> {((json pluck $$) map writeData(json[$],output,constructKeys(keys,$)))},
default -> output ++ {(keys[1 to -1]): json }
}
---
Attributes: writeData(payload.Attributes,{}, '')

Related

Extracting a subset of JSON key-value pairs as an Object from a Parent JSON Object in dataweave 2.0 Mule 4

I have a dataweave challenge which I couldn't figure out without making it complicated.
Input JSON payload
{
"Name" : "Mr.wolf",
"Age" : 26,
"Region" : "USA",
"SubRegion": "Pacific"
}
Output needed
{
"Name" : "Mr.wolf",
"Age" : 26
}
Here is a catch. I am not allowed to use the above shown output format structure in the transform message, or either remove the keys using "-" operation.
So basically, we shouldn't use the below dwl.
%dw 2.0
output application/json
---
(payload - "Region" - "SubRegion")
or
%dw 2.0
output application/json
---
{
"Name" : payload.Name,
"Age" : payload.Age
}
How can we achieve the required output by using Lambdas, Reduce, mapObject, functions or any other operation of choice, other than the restricted methods/usage shown above.
Any solution provided is much appreciated.
is this what you are looking for?
%dw 2.0
output application/json
---
payload filterObject ((value, key,index) -> (index <2 ))
Sounds like filterObject could work for you. Documentation
payload filterObject ((value, key) -> (key ~= "Name" or key ~= "Age"))
Another rendition of the same approach.
%dw 2.0
output application/json
---
payload mapObject {
(($$) : $) if (($$) ~= "Name" or ($$) ~= "Age")
}
The other rendition being:
%dw 2.0
output application/json
---
payload mapObject {
(($$) : $) if (($$$) < 2)
}

Mulesoft Dataweave Converting the key of a mapObject to lower case

Assume the following json with KEY1 and KEY2 in caps. KEY1 and KEY2 needs to be converted to lower case
{
"KEY1": {
"subkey1": "subval1",
"subkey2": "subval2"
},
"KEY2": {
"subkey1": "subval1",
"subkey2": "subval2"
}
}
this needs to be converted to the following json using data weave.
{
"key1": {
"subkey1": "subval1",
"subkey2": "subval2"
},
"key2": {
"subkey1": "subval1",
"subkey2": "subval2"
}
}
I tried the following DW syntax, but it did not work
result : payload mapObject (
lower '$$':$
)
The DW you tried should work if you wrap the expression in parenthesis. This ensures that the lower operator is applied to each of the keys first and then that value is used in the map. So for your example:
%dw 1.0
%output application/json
---
{
result : payload mapObject (
(lower '$$') : $
)
}
Interestingly enough, I get an error (mismatched input ':' expecting ')') in my Transform Message using this DW syntax but I am able to run the project without complaints from Anypoint Studio and the DW runs fine. It also works in MEL with the following:
#[dw("{result : payload mapObject ( (lower '$$' ) : $)}", 'application/json')]
Hope that helps!
You can use the below method to resolve the issue.
%dw 2.0
output application/json
---
{ result: payload mapObject (
(lower ('$$')): $
)
}
In addition if need to lower case also a values then its will be like:
%dw 1.0
%output application/json
---
{
result : payload mapObject (
(lower $$) : (lower $)
)
}

mule : how to convert list of maps to list of JSon in dataweave?

I have input data as list of maps like [{id="200" name="aaa"},{id="100",name="shbd"}].
I want to transform it to JSON like below
{
[
{
id="200",
name="aaa"
},
{
id="100",
name="shbd"
}
]
}
If the fields(keys in map) do no change, then it is simple and straightforward. Now how to transform if I dont know the key values. For eg, what if after sometime the input of map is [{"age":90},{"age","45"}]
It's always better to do specific mapping but you can go with the following , it will transform it into JSON
%dw 1.0
%output application/json
---
payload
As Anirban said, please validate the json you want to transform.
You can use below transformation for o/p specified below:
Transformation
---------------
%dw 1.0
%output application/json
---
payload map {
"id" : $.id,
"name" : $.name
}
---------------
expected output
--------------
[
{
id="200",
name="aaa"
},
{
id="100",
name="shbd"
}
]

Create json array using dataweave

If I have xml like so....
<Root>
<Authority>Water</Authority>
<Sanctions>
<Sanction>
<SanctionCode>11</SanctionCode>
<SanctionDesc>First Sanction</SanctionDesc>
</Sanction>
<Sanction>
<SanctionCode>11</SanctionCode>
<SanctionDesc>Second Sanction</SanctionDesc>
</Sanction>
</Sanctions>
</Root>
Using DataWeave how can I create a json array of Santions using only the SanctionDesc?
I've tried this but it's not right...
%dw 1.0
%output application/json
---
records: payload.Root map {
Authority: $.Authority,
sanctions: $.Sanctions.Sanction map [$.SanctionDesc]
}
I want my output to look like this...
{
"records": [{
"Authority": "Water",
"sanctions": ["First Sanction", "Second Sanction"]
}]
}
Try this
%dw 1.0
%output application/json
---
records: {
Authority: payload.Root.Authority,
sanctions: payload.Root.Sanctions..SanctionDesc
}
Or
%dw 1.0
%output application/json
---
records: {
Authority: payload.Root.Authority,
sanctions: payload.Root.Sanctions.*Sanction map $.SanctionDesc
}
Hope this helps.
Understading the map operator is the key when picking and choosing elements from input payload. Map operator goes through all the array elements on the left hand side and we can pick the values from on right hand side, Giving example from Mulesoft portal
%dw 1.0
%output application/json
users: ["john", "peter", "matt"] map ((firstName, position) -> position ++ ":" ++ upper firstName)
Output:
{
"users": [
"0:JOHN",
"1:PETER",
"2:MATT"
]
}
See link below:
https://docs.mulesoft.com/mule-user-guide/v/3.8/dataweave-operators#map

concatenate XML values using dataweave mule

We have a scenario where we need to concatenate all XML node values to String.
input XML
<root>
<line>1</line>
<line>2</line>
<line>3</line>
<line>4</line>
</root>
Output to String
1234
Please let me know how can i achieve in form of String.
Thanks in advance.
Referring DataWeave Reference Documentation at Reduce section:
Transform
%dw 1.0
%output application/json
---
concat: ["a", "b", "c", "d"] reduce ($$ ++ $)
Output
{
"concat": "abcd"
}
Therefore, you can try something like this: concat: payload.root.*line reduce ($$ ++ $)
Try with this:
%dw 2.0
output application/json
---
{
result: payload.root.*line reduce ((item ,acc="") -> acc ++ item)
}