csv to json conversion where some tags may not come in random - mule

I have a csv input like below: Notice that the tag Edible is not coming for the second set of values. Also notice that the data for one object is coming in columns as well as three rows:
Key|Value|ConcatenatedString
Name|Fruit|"apple,orange,pineapple"
Status|Good|"apple,orange,pineapple"
Edible|Yes|"apple,orange,pineapple"
Name|Furniture|"chair,table,bed"
Status|Good|"chair,table,bed"
I need it in the below json format:
{
Name:"Fruit",
Status:"Good",
Edible:"Yes"
ConcatenatedString:"apple,orange,pineapple"
},
{
Name:"Furniture",
Status:"Good",
Edible:null
ConcatenatedString:"chair,table,bed"
}
I was using the below code when all the tags were coming for all objects. But now that some tags may not come at all I am not sure how to handle this as I was using a position based approach:
%dw 2.0
input payload application/csv separator='|'
output application/json
---
payload map
{
Name:payload[(($$)*4)+0].Value,
Status:payload[(($$)*4)+1].Value,
Edible:payload[(($$)*4)+2].Value,
ConcatenatedString:payload[(($$)*4)+0]."ConcatenatedString"
}
filter ($.Name!= null)
Thanks in advance,
Anoop

here is my answer.
%dw 2.0
input payload application/csv separator="|"
output application/json
---
payload
groupBy ((item, index) -> item.ConcatenatedString)
pluck ((value, key, index) -> {
Name: (value filter ((item, index) -> item.Key == "Name")).Value[0],
Status: (value filter ((item, index) -> item.Key == "Status")).Value[0],
Edible: (value filter ((item, index) -> item.Key == "Edible")).Value[0],
ConcatenatedString: key
})
Basically first you need to group by the criteria you want to group by. In your case ConcatenatedString. This returns
{
"chair,table,bed": [
{
"Key": "Name",
"Value": "Furniture",
"ConcatenatedString": "chair,table,bed"
},
{
"Key": "Status",
"Value": "Good",
"ConcatenatedString": "chair,table,bed"
}
],
"apple,orange,pineapple": [
{
"Key": "Name",
"Value": "Fruit",
"ConcatenatedString": "apple,orange,pineapple"
},
{
"Key": "Status",
"Value": "Good",
"ConcatenatedString": "apple,orange,pineapple"
},
{
"Key": "Edible",
"Value": "Yes",
"ConcatenatedString": "apple,orange,pineapple"
}
]
}
And then you iterate with pluck by every key value pair and filter the elements you want to map.

Related

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

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

Mule 3 convert a json object in to an array

I have the below dynamic response coming from third party API, now I need to transform only the particular JSON object ("MyValues") into an array.
The payload here is sample is is very large .
Current Output:
{
"Body": {
"Status": "200",
"Result": {
"MyValues":{
"Name":"ABC TEST",
"Phone":"1234"
}
}
}
}
Expected Output:
{
"Body": {
"Status": "200",
"Result": {
"MyValues":[{
"Name":"ABC TEST",
"Phone":"1234"
}]
}
}
}
You can use pattern matching based on the type received, array or object. I created a recursive function to find the instances of a key name and perform the change in a generic way.
Example:
%dw 1.0
%output application/json
%function convertToSingleArray(x, key)
x match {
// OPTIONAL :array -> x map convertToSingleArray($, key),
:object -> x mapObject {($$): [$] when ( (($$ as :string) == key) and ((typeOf $) as :string == ":object")) otherwise convertToSingleArray($, key)
},
default -> x
}
---
convertToSingleArray(payload, "MyValues")

How to map certain keys of an array to make another one in mule 4

I have an array -
[
{
"Number": "12345",
"abc": {
"group": "abc",
"operation": "Create"
},
"def": {
"group": "def",
"operation": "Create"
}
},
{
"Number": "45678",
"xyz": {
"group": "xyz",
"operation": "Update"
},
"sdf": {
"group": "sfd",
"operation": "Delete"
}
}
]
and need to convert into this form -
[
{
"Number": "12345",
"group": "abc",
"operation": "Create"
},
{
"Number": "12345",
"group": "def",
"operation": "Create"
},
{
"Number": "45678",
"group": "xyz",
"operation": "Update"
},
{
"Number": "45678",
"group": "sfd",
"operation": "Delete"
}
]
Trying to write dataweave expression for the same. The issue is that abc, def, xyz and all are objects which may or maynot come and can have different values.
Another way to handle this:
%dw 2.0
output application/json
---
payload flatMap ((item, index) ->
(item - "Number") pluck {
"Number": item.Number,
($)
}
)
The approach is mostly the same, but here is the explanation: we use map to iterate, but with flatMap instead since we know we will be returning multiple items from each instance. Then the first thing we do is remove the key Number from the item since we only want to build a new object for each key that isn't Number. Then we can pluck, which gives us access to each key and value; from here we build a new object with our item's number value, and expand the entire object we plucked into that object. When using an anonymous function like this, the $, $$, $$$, etc represent the functions parameters - in pluck's case value, key, index. The parentheses we put around $ means to expand the entire object into our object; in javascript this is similar to { ...props, anotherKey: 'value' }. This means we don't really need to know or care about the structure of that object, which is useful if we have a potentially flexible schema.
You need to map each element, then filter each object to eliminate the attribute Number, and use pluck to convert each remaining key into an array. I used flatMap to concatenate each resulting array from each pluck into the response.
%dw 2.0
output application/json
---
payload flatMap ((item, index) ->
item
filterObject ((value, key, index) -> !(key ~= "Number"))
pluck ((value, key, index) -> {Number: item.Number, group: value.group, operation: value.operation})
)

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

Dataweave in Mule - Change value Array of Objects

I get a payload as input in the message transform component. It is an Array with Objcts:
[
{
"enterprise": "Samsung",
"description": "This is the Samsung enterprise",
},
{
"enterprise": "Apple",
"description": "This is the Apple enterprise ",
}
]
I have a variable that replaces the description and the output that I want is:
[
{
"enterprise": "Samsung",
"description": "This is the var value",
},
{
"enterprise": "Apple",
"description": "This is the var value",
}
]
I tried to use:
%dw 2.0
output application/java
---
payload map ((item, index) -> {
description: vars.descriptionValue
})
But it returns:
[
{
"description": "This is the var value",
},
{
"description": "This is the var value",
}
]
Is possible to replace only the description value keeping the rest of the fields? Avoiding adding the other fields in the mapping.
There are many ways to do this.
One way to do it is to first remove the original description field and then add the new one
%dw 2.0
output application/java
---
payload map ((item, index) ->
item - "description" ++ {description: vars.descriptionValue}
)
Otherwise you can use mapObject to iterate over the key-value pairs of each object and with pattern matching add a case for when the key is description.
I prefer this second way of doing it when I want to do many replacements.
%dw 2.0
output application/java
fun process(obj: Object) = obj mapObject ((value, key) -> {
(key): key match {
case "description" -> vars.descriptionValue
else -> value
}
})
---
payload map ((item, index) ->
process(item)
)