Filter Payload with Dataweave for a Set Variable component - anypoint-studio

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

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

Check if an array contains a value Query in Cumulocity REST API

I have a managed object of type “ABC” with a fragment “A”, that has sub-structure as following:
{
"type": "ABC",
"A": {
"value": ["B", "C"]
}
}
How would one create a filter/query that would check if "A" fragment contains “C” in the "value" array?
That query fails:
{{url}}/inventory/managedObjects?query=$filter=(type+eq+'ABC'+and+A.value+has+‘C‘)
With
{
"error": "inventory/Invalid Data",
"message": "Find by filter query failed : Query '$filter=(type eq 'ABC' and A.value has ‘C‘)' could not be understood. Please try again.",
"info": "https://www.cumulocity.com/guides/reference-guide/#error_reporting"
}
Cumulocity doc about querying REST API.
Solution:
Use eq instead of has:
{{url}}/inventory/managedObjects?query=$filter=(type+eq+'ABC'+and+A.value+eq+‘C‘)
I couldn't find a source but the following is working for me with the expected result:
{{url}}/inventory/managedObjects?query=$filter=(type+eq+'ABC'+and+A.value+eq+'C')
So basically you need to use the eq operator for your use case.

Mulesoft 4 Dataweave for loop and key value pair inside EXCEL TO JSON transformation

I have a data weave transformation converting an excel file to JSON, I had to change the value of an element (column of the file) as per the key-value pair values stored in a variable.
Please let me know how to achieve this.
Below is my data weave which converts 600 rows in the file to a JSON. However, I need to change the value for Brand as per the key-value pair mapping I stored in a variable.
%dw 2.0
output application/json
---
payload map(payload01,index01)->{
city: payload01.City,
province: payload01.Province,
phone: payload01.Phone,
fax: payload01.FAX,
email: payload01.EMAIL,
Brand: payload01.'Fuel Brand'
}
I understand that you want to use the value in attribute 'Fuel Brand' of the input payload to be used as the index in a variable:
%dw 2.0
output application/json
---
payload."Sheet Name" map(payload01,index01)-> {
city: payload01.City,
...
Brand: vars.brandsMapping[payload01.'Fuel Brand']
}
For example if the input is (note: I removed other attributes to simplify the example):
[{City=City A, Fuel Brand=brand1}, {City=City B, Fuel Brand=brand3}]
And the variable vars.brandsMapping contains:
{brand1=The brand1, brand2=The brand2, brand3=The brand3}
The output will be:
[
{
"city": "City A",
"Brand": "The brand1"
},
{
"city": "City B",
"Brand": "The brand3"
}
]
UPDATE: Since you clarified that you want to a dynamic mapping, the method that can be used for that is mentioned at the documentation page: https://docs.mulesoft.com/mule-runtime/4.1/dataweave-cookbook-map-based-on-an-external-definition

Mule Dataweave : Filter in combination with Default function not working

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"