Mule Dataweave : Filter in combination with Default function not working - mule

Im using Mule dataweave, here is my request, i want to filter my request to code == "P" if request containing Code = p not present then always default to code == "C" because code = C always present in the incoming request.
Request:
{
"addresses": [
{
"contact": 0,
"code": "P",
"TypeDescription": "POSTAL",
"postcode": "1007",
"State": "TamilNadu",
"Description": "Test",
},
{
"contact": 1,
"code": "C",
"TypeDescription": "PHYSICAL",
"postcode": "Bangalore",
"State": "",
"Description": "NEW",
}
]
}
Dataweave:
%dw 1.0
%output application/json
---
payload.addresses filter $.code == "P"
It is working fine and filtering out the P containing list, but when try filter in combination with default it dont wont.
I have tried as below in dataweave payload.addresses filter $.code == "P1" default "anything here as of now".
Since in the above response i'm filtering P1 which is not present in the request hence im expecting the default stuff in the response. But it is not working.
Note: Using when and otherwise, bringing the list twice. I need only one list as response either Code P containing list or C containing list.
Using MUle 3.8.5 V. Please let me know your thoughts. Thanks in advance.

From what I understand, Dataweave works from right to left, so in this case is evaluating like this:
'"P1" default "anything here as of now"' resolves to "P1"
run 'filter $.code == "P1"' over 'payload.addresses'
Of course that first option will always evaluate to "P1" so the default is essentially ignored. You need to use parentheses around the rest of the expression, then follow it with default. Now it will evaluate the parentheses then the default expression.
eg: (payload.addresses filter $.code == "P1") default "anything here as of now"
This is not a good example though, as filter will return an empty list if none of the options match, not null, so the default won't work. You could try something like in this answer: https://stackoverflow.com/a/44431546/2614624

Create a default value in local variable and use an OR condition while filtering.
Example below.
{
biggerThanTwo: [0, 1, 2, 3, 4, 5] filter (($ > 2) OR ($ ==1))
}

Here is my Solution. As #Clinton mentioned Filter returns Empty array not null, here is the way it worked out
%dw 1.0
%output application/java
%var conditionalRoute = payload.addresses filter $.addressTypeCode == "P"
conditionalRoute when conditionalRoute != [] otherwise "anything here as of now"

Related

Dynamic CSV with Header only once

I have a request to parse a JSON payload and then create columns dynamically based on a condition.
There should be a Groups column with header. For any additional groups the employee is in, they will be in a column with no header.
If the member is in one group it makes sense I can do something like the following:
%dw 2.0
output application/csv separator=","
var employeesPayload = payload
---
employeesPayload filter ($.workEmail != '' and $.companyEmploymentType.isContractor == false) map (employee) -> {
"Employee ID": employee.employeeNumber,
"Name": employee.preferredFirstName default employee.firstName ++ ' ' ++ if (employee.preferredLastName == '' or employee.preferredLastName == null) employee.lastName else employee.preferredLastName,
"Email": employee.workEmail,
"Groups": employee.workState
}
i.e the table should look similar to the following:
But, how do I add additional columns without headers?
i.e if I want to add a user like Tito (row 9) in the screenshot, how can I build this dynamically?
You can add additional fields dynamically by mapping the payload. If you want the header to be empty you can set the key to an empty string. Note that you can not skip columns, if there is no content you need to at least output an empty string.
Example:
%dw 2.0
output application/csv
---
payload map {
($), // just reusing the input payload as is
d: $$, // some calculated field with a header
"": if (isEven($$)) $$ else "", // calculated field with an empty name, only on some condition
"": $$ // another calculated field with an empty name
}
Input:
[
{
"a": "a1",
"b": "b1",
"c": "c1"
},
{
"a": "a2",
"b": "b2",
"c": "c2"
},
{
"a": "a3",
"b": "b3",
"c": "c3"
}
]
Output:
a,b,c,d,,
a1,b1,c1,0,0,0
a2,b2,c2,1,,1
a3,b3,c3,2,2,2

Need to change csv header from camel case to snake case in dataweave

I am working on a pipeline to dynamically dump all columns from the salesforce object to the S3 bucket.
I get all columns for a salesforce object using describe object API. I store all columns into a variable and then create a big SOQL query out of it and submit a bulk query job v2.
Now, this is the main problem. The Column name I am getting from the salesforce connector is in camelCase
[{
"Id": 123,
"FirstName": "Manual",
"MasterRecordId__c" :"abc"
},
{
"Id": 456,
"FirstName": "John",
"MasterRecordId__c" :"def"
}]
But I want column names to be in snake case
[{
"Id": 123,
"first_name": "Manual",
"master_record_id__c":"abc"
},
{
"Id": 456,
"first_name": "john",
"master_record_id__c":"def"
}]
I understand mulesoft has an underscore function to do the same thing, but I am not able to apply any function at "key" level.
Any lead would be really helpful. Please let me know for any questions.
You just have to use mapObject along with the underscore function
%dw 2.0
import underscore from dw::core::Strings
output application/json
---
payload map ((item) ->
item mapObject ((value, key) -> {
(underscore(key)): value
})
)
In case you want Id field to remain as it is, give a try like below:
%dw 2.0
import * from dw::core::Strings
output application/json
---
payload map ($ mapObject ((value, key, index) -> if (capitalize(key as String) == key as String)
{
(key): value
}
else
{
(underscore(key)): value
}))

Delete first and last quote mule 3

I try to delete the quotes around the payload that is incoming from http request, so I can use it as request for an another call (mule 3).
I use the next transformation syntax;
%dw 1.0
%output application/json
---
(payload.value.id) joinBy " or id eq "
and I get this as payload;
{
"#odata.context": "https://test.service.com/services/repo/v1/odata/$metadata#Incident",
"value": [
{
"id": "7001fc4a-8c8d-43f5-abc7-666666cbdd63",
"createDate": "2022-01-24T16:47:22Z"
},
{
"id": "ff8aeb42-210c-49d7-aa25-12da825b6b89",
"createDate": "2022-01-24T19:35:06Z"
}
]
}
I want to retrieve only the Id's and add id eq or see below.
how ever my desire output need to be like this;
9001fc4a-8c8d-43f5-abc7-146945cbdd63 id eq or
ff8aeb42-210c-49d7-aa25-19da825b6b89 id eq or
88eb39ee-d8f7-462c-9b69-1d4a1e3bf994 id eq or
66af209d-7635-4f51-95fd-204e2faea223 id eq or
5b93cf0d-e397-4cea-914b-3842c3aa0847 id eq or
I have tried with replace /["]/ with "" and with alot of connectors only I dont get it done.
In mule 4 it's just changing the to output text/plain and it removes al the quotes only mule 3 not.
Anyone experience with this.
Thanks for helping.
text/plain is reserved for fixed format in DataWeave for Mule 3. Try setting the output to application/java and the use it.

how properly to add and remove elements from payload? (or replace on condition)

So I have payload that have old type of attributes, and I want to migrate them to be as new ones that all the rest logic is using. So before do validation I want modify it a bit.
Currently I manage to add and remove in separate transforms, but should it be possible to do in one go?
example payload:
{
"country": "Country",
"town": "Town",
"district": "Dist",
"owner": "Owner"
}
and output should be:
{
"country": "Country",
"city": "Town",
"area": "Dist",
"owner": "Owner"
}
so I add transform:
%dw 1.0
%output application/json
---
payload ++ {city: payload.town}
when
payload.town != null
otherwise
payload ++ {area: payload.distrinct}
when
payload.distrinct != null
otherwise
payload
I want to check if payload have no null values in town key and add new key city with town key value, and same check if distrinct is not null then add its value as area key. However its happening only for city (I know it will be added at the bottom, but order is not a problem in my case) however keys may not present (it may no town, or may no distrinct or may no both)
And on next transform:
%dw 1.0
%output application/json
---
payload -- {town: payload.town}
when
payload.town != null
otherwise
payload
I try to check if keys exist then delete old ones, but no luck on such :(
Any help?
That's too complicated. Instead of adding and removing keys you can just use mapObject to transform each key. Then it becomes trivial to parametrize the transformation. Also using default is simpler than when...otherwise when a value is null.
%dw 1.0
%output application/json
%var keyMap={ town: "city", district: "area" }
%function replaceKey(keyName) (keyMap[keyName] default keyName)
---
payload mapObject ( (replaceKey($$)) : $ )

Filter Payload with Dataweave for a Set Variable component

For the Mulesoft 4.2 Set Variable component, I want to assign a simple String value pulled from a single specific record from an incoming JSON payload.
In my case, taking just the value from the 'country' field from below example:
[
{
"salesID": "4404Bob Builder210032011-02-18T15:52:21+0.00",
"id": "4404",
"firstName": "Bob",
"lastName": "Builder",
"address": "181 Construction Road, Adelaide, NSW",
"postal": "21003",
"country": "New Zealand",
"creationDate": "2011-02-18T15:52:21+0.00",
"accountType": "personal",
"miles": 17469
}
]
A non-dynamic way to do this is like:
payload[0].country
I believe the best way to do this is with the filter function. The below option gives me the entire object, but I just want the country field.
payload filter ($.id == "4404")
Map function seems to be overkill for this since I only want the value, itself. I must be missing the syntax to get at the country field.
I did some more investigating, and this solution got me close enough to what I wanted:
https://stackoverflow.com/a/43488566/11995149
For my code example using filter, I had to surround the whole expression in parenthesis, and then I can access the field with a dot reference,
but below code gives String value as a single record within an array:
(payload filter ($.id == "4404")).country
[
"New Zealand"
]
In my case, I know that just one result will be returned from the filtered payload, so I could get just the String value with:
(payload filter ($.id == "4404"))[0].country
enter image description here
Can you try any of below options:
1) (payload groupBy ((item, index) -> item.id))["4404"][0].country
OR
2) (payload map ((item, index) -> if(item.id == "4404") item.country else ""))[0]
Thanks,
Ashish