Compare the inputs and get the response? - mule

Input 01:
{
"labelItems": [{
"label": "manager",
"role": "MA"
}, {
"label": "Developer",
"role": "DEV"
}]
}
Input 02:
{
"List": [{
"id": "M123",
"label": "Manager"
},
{
"id": "L240",
"label": "Lead"
},
{
"id": "D250",
"label": "Developer"
}
]
}
Final output:
{
"Labels": [{
"id": "M123",
"role": "MA"
},
{
"id": "D250",
"role": "DEV"
}
]
}
Can anyone provide me the above desired final output response, we have two input payloads and compare two payloads with the label field and get the id & role fields from the array of the list.
Thanks in Advance,

One way would be to iterate on Input 02 ( I have set Input 01 as the payload to this script) and pass over the label to filter the payload, to procure the corresponding role. Have used capitalize since the manager in payload (Input 01) starts with lowercase m while the same starts with Uppercase m in Input 02 label for id M123.
%dw 2.0
output application/json
import * from dw::core::Strings
var inp2 = {
"List": [{
"id": "M123",
"label": "Manager"
},
{
"id": "L240",
"label": "Lead"
},
{
"id": "D250",
"label": "Developer"
}
]
}
---
Labels: inp2.List map ((item, index) -> {
id: item.id,
role: (payload.labelItems filter (capitalize($.label) == item.label )).'role'[0]
}) filter (!($.role == null))
Another modification to this could be:
%dw 2.0
output application/json
import * from dw::core::Strings
var inp2 = {
"List": [{
"id": "M123",
"label": "Manager"
},
{
"id": "L240",
"label": "Lead"
},
{
"id": "D250",
"label": "Developer"
}
]
}
var interim = payload.labelItems map {
(capitalize($.label)): $.role
}
---
Labels: inp2.List map ((item, index) -> {
id: item.id,
role: interim[(item.label)][0]
}) filter (!($.role == null))

Another way to do this is by using joins. I have used leftJoin for joining the arrays.
%dw 2.0
import * from dw::core::Arrays
output application/json
var inp2 = {
"List": [{
"id": "M123",
"label": "Manager"
},
{
"id": "L240",
"label": "Lead"
},
{
"id": "D250",
"label": "Developer"
}
]
}
---
Labels: leftJoin (payload.labelItems, inp2.List,
(labelItems)-> lower(labelItems.label), (listItems) -> lower(listItems.label))
map {
id: $.r.id,
role: $.l.role
}

You can iterate over input 1 and compare the current item's label with label in in2's list to get the corresponding id
%dw 2.0
output application/json
var in1={
"labelItems": [{
"label": "manager",
"role": "MA"
}, {
"label": "Developer",
"role": "DEV"
}]
}
var in2={
"List": [{
"id": "M123",
"label": "Manager"
},
{
"id": "L240",
"label": "Lead"
},
{
"id": "D250",
"label": "Developer"
}
]
}
---
Labels: in1.labelItems default [] map (item, index) -> {
id: in2.List[?(lower($.label) == lower(item.label))][0].id,
role: item.role
}
Have used lower to avoid any case sensitivity

Related

How to apply filter for nested arrays in mulesoft dataWeave

I tried to filter below json payload characters[] array which is having result as 'valid' and data[] array name as 'WBB' and priority as '1'
I tried below code but not working can some one help me ?.
flatten(payload.offers.category.characters) filter ((item, index) -> item.result=='valid' and flatten(item.data) filter ((item, index) -> item.name=='WBB' and item.priority==1))
Json payload
{
"offers": [
{
"id": 100,
"name": "Test1",
"category": {
"characters": [
{
"result": "valid",
"data": [
{
"name": "WBB",
"priority": 1
},
{
"name": "ILL",
"priority": 2
}
]
}
]
}
},
{
"id": 200,
"name": "Test2",
"category": {
"characters": [
{
"data": [
{
"name": "ISS",
"priority": 1
},
{
"name": "ILL",
"priority": 2
}
]
}
]
}
},
{
"id": 300,
"name": "Test3",
"category": {
"characters": [
{
"data": [
{
"name": "WSS",
"priority": 1
},
{
"name": "ILL",
"priority": 2
}
]
}
]
}
}
]
}
Expected payload
[
{
"name": "WBB",
"priority": 1
}
]
flatten((flatten(payload.offers..characters) filter $.result == "valid").data) filter ($.name=="WBB" and $.priority == 1)
flatten(payload..data) filter ((item, index) -> item.name == 'WBB' )

Replace specific values in the array using dwl 1.0

Problem with using mapObject function properly.
Trying to retain existing array structure but calculate number of vehicles and properties and update the existing array that contains the value.
GENERAL data comes from one source, VEHICLE data comes from another source, PROPERTY data comes from another source. So when merging, I have to update GENERAL data with count of other source data.
Also GENERAL is an array object, it will always have 1. So using GENERAL[0] is safe and fine.
Original Payload
[
{
"commId": "1",
"GENERAL": [
{
"ID": "G1",
"VEHICLE_COUNT": "TODO",
"PROPERTY_COUNT": "TODO"
}
],
"VEHICLE": [
{
"ID": "V1-1"
},
{
"ID": "V1-2"
}
],
"PROPERTY": [
{
"ID": "P1-1"
}
]
},
{
"commId": "2",
"GENERAL": [
{
"ID": "G2",
"VEHICLE_COUNT": "TODO",
"PROPERTY_COUNT": "TODO"
}
],
"VEHICLE": [
{
"ID": "V2-1"
}
],
"PROPERTY": [
{
"ID": "P2-1"
},
{
"ID": "P2-2"
}
]
},
{
"commId": "3",
"GENERAL": [
{
"ID": "G3",
"VEHICLE_COUNT": "TODO",
"PROPERTY_COUNT": "TODO"
}
],
"VEHICLE": [
{
"ID": "V3-1"
},
{
"ID": "V3-2"
},
{
"ID": "V3-3"
}
]
}
]
Tried using map to loop through the payload and tried modifying 2 attribute but only managed to map one but even that is showing wrong output.
test map (item, index) -> {
(item.GENERAL[0] mapObject (value, key) -> {
(key): (value == sizeOf (item.VEHICLE)
when (key as :string) == "VEHICLE_COUNT"
otherwise value)
})
}
Expected output:
[
{
"commId": "1",
"GENERAL": [
{
"ID": "G1",
"VEHICLE_COUNT": "2",
"PROPERTY_COUNT": "1"
}
],
"VEHICLE": [
{
"ID": "V1-1"
},
{
"ID": "V1-2"
}
],
"PROPERTY": [
{
"ID": "P1-1"
}
]
},
{
"commId": "2",
"GENERAL": [
{
"ID": "G2",
"VEHICLE_COUNT": "1",
"PROPERTY_COUNT": "2"
}
],
"VEHICLE": [
{
"ID": "V2-1"
}
],
"PROPERTY": [
{
"ID": "P2-1"
},
{
"ID": "P2-2"
}
]
},
{
"commId": "3",
"GENERAL": [
{
"ID": "G3",
"VEHICLE_COUNT": "3",
"PROPERTY_COUNT": "0"
}
],
"VEHICLE": [
{
"ID": "V3-1"
},
{
"ID": "V3-2"
},
{
"ID": "V3-3"
}
]
}
]
Getting totally wrong output so far:
[
{
"ID": "G1",
"VEHICLE_COUNT": false,
"PROPERTY_COUNT": "TODO"
},
{
"ID": "G2",
"VEHICLE_COUNT": false,
"PROPERTY_COUNT": "TODO"
},
{
"ID": "G3",
"VEHICLE_COUNT": false,
"PROPERTY_COUNT": "TODO"
}
]
Edited: Update for dynamic transform
The below dataweave transform is not particularly attractive, but it might work for you.
Thanks to Christian Chibana for helping me find a dynmaic answer by answering this question: Why does Mule DataWeave array map strip top level objects?
%dw 1.0
%output application/json
---
payload map ((item) ->
(item - "GENERAL") ++
GENERAL: item.GENERAL map (
$ - "VEHICLE_COUNT"
- "PROPERTY_COUNT"
++ { VEHICLE_COUNT: sizeOf (item.VEHICLE default []) }
++ { PROPERTY_COUNT: sizeOf (item.PROPERTY default []) }
)
)
It is dynamic, so everything should be copied across as it comes in, with only the two fields you want being updated.
The output for this transform with the input you supplied is below. Only difference from your desired is that the counts are shown as numbers rather than strings. If you really need them as strings you can cast them like (sizeOf (comm.VEHICLE default [])) as :string,
[
{
"commId": "1",
"VEHICLE": [
{
"ID": "V1-1"
},
{
"ID": "V1-2"
}
],
"PROPERTY": [
{
"ID": "P1-1"
}
],
"GENERAL": [
{
"ID": "G1",
"VEHICLE_COUNT": 2,
"PROPERTY_COUNT": 1
}
]
},
{
"commId": "2",
"VEHICLE": [
{
"ID": "V2-1"
}
],
"PROPERTY": [
{
"ID": "P2-1"
},
{
"ID": "P2-2"
}
],
"GENERAL": [
{
"ID": "G2",
"VEHICLE_COUNT": 1,
"PROPERTY_COUNT": 2
}
]
},
{
"commId": "3",
"VEHICLE": [
{
"ID": "V3-1"
},
{
"ID": "V3-2"
},
{
"ID": "V3-3"
}
],
"GENERAL": [
{
"ID": "G3",
"VEHICLE_COUNT": 3,
"PROPERTY_COUNT": 0
}
]
}
]

Creating a Mango query selector for element that do NOT match

I have a user like so:
{
"_id": "u88888",
"_rev": "27-9f205fb7496645be2f3d717fff376d73",
"name": "Test Testerson",
"type": "user",
"role": "boss",
"training": [
{
"id": "11111",
"name": "training 1"
},
{
"id": "33333",
"name": "training 3"
}
]
}
I'm trying to run a query to find the following:
Is a type, "user"
Has a role of "boss"
Does not have the training of id: "11111"
I do the following selector, however, this user comes up and I'm not sure why:
selector:{
"$and": [
{ "type": "user" },
{ "role": "boss" },
{ "training": { "$ne": { "id": "11111" } } }
]
}
Found an answer. This ended up working:
{ training: { $not: {$elemMatch: {id: "11111" } } }

Mule- Extracting key from Json object using dataweave

I need to extract key and values from json input object to form different json output.
I went through the documentation and other questions asked similar to this where I could found out that $$ gives the key but, in my case it is giving me index but not the key name.
The input json looks like this :{
"key2": "val2",
"key3": "val3",
"key4": "val4",
"key5": "val5",
"key6": "val6"
}
The dataweave code I have written is :
{
"someOtherKey": "val",
properties: {
entry: payload map
{
key:$$,
value:$
}
}
}
After transformation I am getting :
{
"someOtherKey": "val",
"properties": {
"entry": [
{
"key": 0,
"value": "val2"
},
{
"key": 1,
"value": "val3"
},
{
"key": 2,
"value": "val4"
},
{
"key": 3,
"value": "val5"
},
{
"key": 4,
"value": "val6"
}
]
}
}
Here I am expecting output with key name as value for Key
Expected output :
{
"someOtherKey": "val",
"properties": {
"entry": [{
"key": "key2",
"value": "val2"
},
{
"key": "key3",
"value": "val3"
},
{
"key": "key4",
"value": "val4"
},
{
"key": "key5",
"value": "val5"
},
{
"key": "key6",
"value": "val6"
}
]
}
}
The tag pluck worked for me. Here is the example :
{
"someOtherKey": "val",
properties: {
entry: payload pluck
{
key:$$,
value:$
}
}
}
Use mapObject instead of map
%dw 1.0
%output application/json
---
{
key: "val",
key1: "val1",
properties: {
entry: payload mapObject {
key:$$,
value:$
}
}
}
Hope this helps.

Filter same level object values in loop data weave - Mule 3.7

I am trying to filter same level object values in the payload in Dataweave. I was able to loop through but it does not produce the expected output.
Sample Payload:
{
"root": {
"createItem": {
"itemInfo": {
"lines": [{
"lineIdentifier": "4",
"Attributes": "Test1",
"partNumber": "QZRB"
}, {
"lineIdentifier": "10",
"Attributes": "Test3",
"partNumber": "QPR1"
}, {
"lineIdentifier": "12",
"Attributes": "Test4",
"partNumber": "QHT2"
}]
}
},
"ItemResponse": {
"lines": [{
"lineIdentifier": 4,
"itemName": "QZRB",
"status": "FAILED"
}, {
"lineIdentifier": 10,
"itemName": "QPR1",
"status": "COMPLETE"
}, {
"lineIdentifier": 12,
"itemName": "QHT2",
"status": "COMPLETE"
}]
}
}
}
Expected Output:
{
"root": {
"createItem": {
"itemInfo": {
"lines": [ {
"lineIdentifier": "10",
"Attributes": "Test3",
"partNumber": "QPR1"
}, {
"lineIdentifier": "12",
"Attributes": "Test4",
"partNumber": "QHT2"
}]
}
}
}
}
Here's what I am doing:
{
root: {
(payload.root.createItem.itemInfo.lines map ((respLines, indexOfRespLines) -> {
items:payload.root.ItemResponse.lines filter ($.itemName == respLines.partNumber and $.status =='COMPLETE') map
{
item: $.itemName,
attributes: respLines.Attributes
}
}
)
)
}
}
How do I achieve this?
Thanks,
ROA
try this:
%dw 1.0
%output application/json
%var completedLines = payload.root.ItemResponse.lines filter $.status == 'COMPLETE' map $.lineIdentifier as :string
---
{
root: {
createItem: {
itemInfo: {
lines: payload.root.createItem.itemInfo.lines filter (completedLines contains $.lineIdentifier)
}
}
}
}
pay attention to as :string in completedLines, because the lineIdentifier in ItemResponse is a number, while in itemInfo it is a string.