List of map to json using Dataweave - mule

How can i convert list of map to json using dataweave for the below example.
Input is list of map. For example, it has 3 elements id, value1, value2
[
{
"id" : "123",
"value1" : "678"
"value2" : "900"
},
{
"id" : "456",
"value1" : "679",
"value2" : "901"
}
]
Expected output:
Root element is data, value of id (123) is the key and value2, value 3 are elements in the object.
{
"data" : {
"123" : {
"value1" : "678",
"value2" : "900"
},
"456" : {
"value1" : "679",
"value2" : "901"
}
}
}
I tried to implement dataweave script but its not giving the exact output i was looking for. How can i write dataweave script to achieve this?

data: ( payload.*id map '$':payload[$$] - "id") reduce ($$ ++ $)
Should do the trick.

Try the below script
data: {
(payload map {
($.id as :string): $ -- $.id
})
}
Here, id is used as key and from value we remove the corresponding id

Related

How to create a map of Excel file key-value without using column name in Dataweave?

I am reading an excel file (.xlsx) into a json array and I am creating into a map because I want to apply validations to each of the column individually. I am able to access it using the column name like so,
Excel file is :
column A, column B
value of Column A, value of column B
I am accessing it like this :
payload map(item, index) ->
"Column Name A" : item."Column Name A",
"Column Name B" : item."Column Name B"
Where column A and B are the excel column header.
What I want to do is to create the same map but using the column index like
payload map(item, index) ->
item[0].key : item[0],
item[1].key : item[1]
So that I do not have to hard code the excel header name and I can rely on the index of the excel columns.
I have tried using pluck $$ to create a map of Keys but I cannot create a map of keys-value, I am not able to use item[0] as key in a map.
How can I achieve above without using excel column header name?
Expected output should be like this :
{
"Column A " : "value of Column A",
"Column B" : "value of Column B",
"Errors" : "Column A is not valid"
}
Assuming that you'd like to validate each payload item loaded from an Excel file, you could use the following DataWeave expression:
%dw 2.0
output application/json
fun validate(col, val) =
if (isEmpty(val)) {"error": col ++ ": value is null or empty"}
else {}
fun validateRow(row) =
"Errors":
flatten([] << ((row mapObject ((value, key, index) -> ((validate((key), value))))).error default []))
---
payload map (item, index) -> item ++ validateRow(item)
Using the following input payload:
[
{"col1": "val1.1", "col2": "val1.2", "col3": "val1.3"},
{"col1": "val2.1", "col2": "val2.2", "col3": null}
]
would result in:
[
{
"col1": "val1.1",
"col2": "val1.2",
"col3": "val1.3",
"Errors": [
]
},
{
"col1": "val2.1",
"col2": "val2.2",
"col3": null,
"Errors": [
"col3: value is null or empty"
]
}
]
The expression will result in an output slightly different than the one you're expecting, but this version will allow you to have an array of error messages that can be easier to manipulate later on in your flow.
One thing to keep in mind is the possibility to have more than one error message per column. If that's the case, then the DataWeave expression would need some adjustments.
Try just using the index. It should work just fine.
%dw 2.0
output application/json
---
({ "someKey": "Val1", "lksajdfkl": "Val2" })[1]
results to
"Val2"
And if you want to use a variable as a key you have to wrap it in parentheses.
EG, to transform { "key": "SomeOtherKey", "val": 123 } to { "SomeOtherKey": 123 } you could do (payload.key): payload.val
Try this:
%dw 2.0
output application/json
var rules = {
"0": {
key: "Column A",
val: (val) -> !isEmpty(val),
},
"1": {
key: "Column B",
val: (val) -> val ~= "value of Column B"
}
}
fun validate(v, k, i) =
[
("Invalid column name: '$(k)' should be '$(rules[i].key)'") if (rules[i]? and rules[i].key? and k != rules[i].key),
("Invalid value for $(rules[i].key): '$(v default "null")'") if (rules[i]? and rules[i].val? and (!(rules[i].val(v))))
]
fun validate(obj) =
obj pluck { v: $, k: $$ as String, i: $$$ as String } reduce ((kvp,acc={}) ->
do {
var validation = validate(kvp.v, kvp.k, kvp.i)
---
{
(acc - "Errors"),
(kvp.k): kvp.v,
("Errors": (acc.Errors default []) ++
(if (sizeOf(validation) > 0) validation else [])
) if(acc.Errors? or sizeOf(validation) > 0)
}
}
)
---
payload map validate($)
Output:
[
{
"Column A": "value of Column A",
"Column B": "value of Column B"
},
{
"Column A": "",
"Column B": "value of Column B",
"Errors": [
"Invalid value for Column A: ''"
]
},
{
"Column A": "value of Column A",
"Column B": "value of Column C",
"Errors": [
"Invalid value for Column B: 'value of Column C'"
]
},
{
"Column A": null,
"Column C": "value of Column D",
"Errors": [
"Invalid value for Column A: 'null'",
"Invalid column name: 'Column C' should be 'Column B'",
"Invalid value for Column B: 'value of Column D'"
]
}
]

How convert json object to lower case in dataweave 1.0?

Hello I have a json file as payload and strugling to do Transformation to lower case of elements and they values.
{
"Name" : "John".
"e-mails" : ['Email1#mail.com','email2#Gmail.com']
}
if its no array in values then this one works fine like where
but how to deal with arrays?
expected output:
{
"name" : "john".
"e-mails" : ['email1#mail.com','email2#gmail.com']
}
any advice?
You need to use a recursive function to cover for the other types.
%dw 1.0
%output application/json
%function lowerAll(x)
x match {
:object -> $ mapObject {
(lower $$): lowerAll($) // assumes all keys are strings
},
:array -> $ map lowerAll($),
:string -> lower $,
default -> $
}
---
lowerAll(payload)
Input:
{
"Name" : "John",
"e-mails" : ["E1mail1#mail.com","email2#Gmail.com"]
}
Output:
{
"name": "john",
"e-mails": [
"e1mail1#mail.com",
"email2#gmail.com"
]
}

Lookup Country Code from the phone Numbers using Dataweave Mule

My Input Request JSON looks like this below:
{
"phoneNumbers": [{
"phoneNumberType": "mobile",
"phoneNumber": "54112724555"
},
{
"phoneNumberType": "mobile",
"phoneNumber": "16298765432"
}
]
}
I want to generate Output Json Like this :
{
"phoneNumbers": [{
"phoneNumberType": "mobile",
"phoneNumber": "54112724555",
"CountryCode": "ARG"
},
{
"phoneNumberType": "mobile",
"phoneNumber": "16298765432",
"CountryCode": "US"
}
]
}
I derive the countryCode from the PhoneNumber using callingCode and CountryCode Mapping given in csv file.
CALLING_CODE,COUNTRY_CODE
1,US
7,RU
54,AR
20,EG
32,BE
33,FR
505,NI
506,CR
1876,JM
1905,CA
1939,PR
262262,RE
262269,YT
.,.
.,.
I have used the fileConnector to read the CSV File and stored it in Vars.CallingCodeMapping.
I have to do lookup phoneNumber with calling code by passing first letter from the phonenumber matching return countryCode then first two letter ....firstsixLetter if nothing matches return NA.
Given this input as payload
[
"54112724555",
"16298765432"
]
And this csv in a var called country_codes
%dw 2.0
output application/json
var codeByCode = vars.country_code groupBy ((item, index) -> item.CALLING_CODE)
/**
* Returns the Country code or Null if not found
*/
fun lookupCountrCode(phoneNumber:String): String | Null =
//map the each sub part to a country code or null
(0 to 6 map ((index) -> codeByCode[phoneNumber[0 to index]])
//Filter non null and take the first this will return null if array is empty
filter ((item, index) -> item != null))[0]
---
payload map ((item, index) -> lookupCountrCode(item))
Outputs
[
[
{
"CALLING_CODE": "54",
"COUNTRY_CODE": "ARG"
}
],
[
{
"CALLING_CODE": "1",
"COUNTRY_CODE": "US"
}
]
]

Postgres query to return rows where json in the json column contains array elements more than one

We are using Postgres DB , in that we have one table contains column of type JSON , format is like below
{
"name" : "XXX",
"id" : "123",
"course" :[
{
"name" : "java",
"tutor":"YYYY"
},
{
"name" : "python",
"tutor":"ZZZZ"
}
]
}
{
"name" : "XXX",
"id" : "123",
"course" :[
{
"name" : "java",
"tutor":"YYYY"
},
{
"name" : "python",
"tutor":"ZZZZ"
}
]
}
like this for example we have two rows , and in the json column we have each like above
i want to Postgre query , which will check the number of elements in the course array and if it is more than one , then only return that row
am not getting how to count the array elements from inside the json key
can any please suggest
why not just json_array_length?.. eg:
f=# with c(j) as (values('{
"name" : "XXX",
"id" : "123",
"course" :[
{
"name" : "java",
"tutor":"YYYY"
},
{
"name" : "python",
"tutor":"ZZZZ"
}
]
}'::json))
select json_array_length(j->'course') from c;
json_array_length
-------------------
2
(1 row)
so smth like
select * from table_name where json_array_length(j->'course') > 1

Lookup list of Maps variable in data weave script

I have a list of maps (listOfMapsObject) like below
[
{
"Id" : "1234",
"Value" : "Text1"
},
{
"Id" : "1235",
"Value" : "Text2"
}
]
I would like access "Value" field for a given Id in dataweave script.
For example: For Id = 1234, Text1 should be returned.
%dw 1.0
%output application/json
%var listOfMapsObject = flowVars.listOfMaps
---
payload map {
"key" : $.key,
"data" : lookup Value field in listOfMapsObject by given key
}
Approch suggested by #'sulthony h' is fine but it will end up in performance issue if you large number of data in pyload and listOfMapsObject. As filter is used , for each record of payload script will loop for all the entries in flowVars.listOfMaps.
Following will work fine and map key value only once.
%dw 1.0
%output application/json
%var dataLookup = {(flowVars.listOfMaps map {
($.Id): $.Value
})}
---
payload map {
key : $.key,
data : dataLookup[$.key]
}
Output-
[
{
"key": "1234",
"data": "Text1"
},
{
"key": "1235",
"data": "Text2"
}
]
Where Payload -
[
{
"key" : "1234"
},
{
"key" : "1235"
}
]
And -
[
{
"Id" : "1234",
"Value" : "Text1"
},
{
"Id" : "1235",
"Value" : "Text2"
}
]
Hope this helps.
I create my own object with the slightly similar object and successfully access "value" field with the following DataWeave expression:
%dw 1.0
%output application/json
%var listOfMapsObject = flowVars.listOfMaps
---
payload map using(data = $) {
"key" : data.key,
"data" : (listOfMapsObject filter $.id == data.key).value reduce ($$ ++ $)
}
You can modify it with your own object, e.g.: replace the "id" with "Id". Test and evaluate the result by using filter, flatten, reduce, etc.