Array of objects to a single object containing all said objects Dataweave - mule

I am trying to transform the below Array of Objects input:
[
{
"Id": "3",
"Code": "4190484",
"Expense": "Huge Expense "
},
{
"Id": "4",
"Code": "271",
"Expense": "Big Expense"
},
{
"Id": "3",
"Code": "433",
"Expense": "No Expense"
}
]
to this Output of a single object:
{
"Id": "3",
"Code": "4190484",
"Expense": "Huge Expense ",
"Id": "4",
"Code": "271",
"Expense": "Big Expense",
"Id": "3",
"Code": "433",
"Expense": "No Expense"
}
How would you accomplish this in Dataweave?

You can also use the dynamic elements feature of the language:
%dw 2.0
output application/json
---
{(payload)}
Like #aled explained in his answer, you should not be using duplicate keys in JSON.

You can use the reduce() function but be warned that using duplicate keys in JSON is implementation dependent. I think it is a bad design to use duplicate keys in JSON. It might lead to unexpected behaviors. Some implementations might ignore the duplicates. For example DataWeave will return only one Id of the resulting object with payload.Id.
If even after what I mentioned you still want to go ahead it this is an example:
%dw 2.0
output application/json
---
// I don't recommend to use duplicate keys
payload reduce ((item, acc = {}) -> acc ++ item)

Related

How to filter entities with nested arrays with CosmosDB

I have an entity like this:
{
"id": "xxxx",
"attributes": [{
"name": "name-01",
"value": "value-01"
}, {
"name": "name-02",
"value": "value-02"
}
]
}
Our "questions" to data usually: Give me entities with attribute or attribute with particular value;
in SQL it was written like as:
select *
from c
where
and array_contains(c.attributes, { "name": "name-01", "value": "value-01" }, true)
and array_contains(c.attributes, { "name": "name-02", "value": "value-02" }, true)
but I would like to extend a model to allow have suggestion of values in each attribute by transform an entity to:
{
"id": "xxxx",
"attributes": [{
"name": "name_01",
"value": "value-01",
"suggestions": ["a", "b", "c"]
}, {
"name": "name_02",
"value": "value-02",
"suggestions": ["a", "d", "e"]
}
]
}
With that structure I would like to ask: Give me all entities that has specified attribute and value equals to "XYZ" or suggestions array contains "XYZ";
In general scenario if always add value into array of suggestions the ask would be "Give me all entities that has specified attribute and suggestions contains XYZ"
N.B. Also I would like to make queries : Give me all entities that has more ALL specified attributes with constraints per each by suggestions?
Please suggest how to write such queries or rebuild a structure of entities in Cosmos DB;
P.S. We can technically switch from SQL to other protocol to better make such queries;
This should be doable using ARRAY_CONTAINS along with iterating the attributes array.
Give me items with value "value-01" or suggestion "f":
SELECT DISTINCT VALUE(c)
FROM c JOIN attr IN c.attributes
WHERE attr["value"] = "value-01" OR ARRAY_CONTAINS(attr.suggestions, "f")
Give me items with value "value-01" or both suggestions "a" and "f":
SELECT DISTINCT VALUE(c)
FROM c JOIN attr IN c.attributes
WHERE attr["value"] = "value-01" OR
ARRAY_CONTAINS(attr.suggestions, "a") AND ARRAY_CONTAINS(attr.suggestions, "f")

Karate: compare csv data with api response

I have a use case where I want to assert on a API response and compare it with the csv data.
Step1:
Csv file: *test.csv*
id,date,fullname,cost,country,code
1,02-03-2002,user1,$200,Canada,CAN
2, 04-05-2016,user2,$1500,United States, USA
I read the csv file and store it in a variable
def var1 = read(test.csv)
So now, var1 is a list of jsons based on my csv
var1 = [
{
"id":1,
"date":"02-03-2002",
"fullname": "user1",
"cost": "$200",
"country": "Canada",
"code": "CAN"
},
{
"id":2,
"date":"04-05-2016",
"fullname": "user2",
"cost": "$1500",
"country": "United States",
"code": "USA"
}
]
Step2:
I hit my api and get a response
Given url "https://dummyurl.com
Given path "/userdetails"
When method get
Then status 200
* def apiResponse = response
Step 3:
My api returns a list response which is:
{
"id":1,
"date":"02-03-2002",
"fullname": "user1",
"cost": "$200",
"country": {
"name": "Canada",
"code": "CAN"
}
},
{
"id":2,
"date":"05-04-2012",
"fullname": "user2",
"cost": "$1500",
"country": {
"name": "United States",
"code": "USA"
}
},
...and more 100 records..
]
Step 4:
So there are two assertions now which I wanted to perform
Get the count of csvresponse and apiresponse and compare which I did using the .length operator
Secondly, I want to confirm if each csv records are matching with each api response.
And if possible in my case id key from csv and apiresponse is primary key, so if I can iterate on id and match the api response for any discrepancy.
Let me know if this is readable for you and if I was able to explain my use case.
Thanks for your earlier response.
Please read up on the match contains syntax, that's all you need: https://github.com/intuit/karate#match-contains
So this one line should be enough:
* match var1 contains response
Also look at this answer in case the new contains deep helps: https://stackoverflow.com/a/63103746/143475
Try to avoid iterating, it is not needed for most API tests. But you can certainly do it. Look at these answers:
https://stackoverflow.com/a/62567262/143475
Also read this - because I suspect you are trying to over-complicate your tests. Please don't. Write tests where your are 100% sure of the "shape" of the response as far as possible: https://stackoverflow.com/a/54126724/143475
And please please read the docs. It is worth it.

Mule:Dataweave Iteration not working

I am trying to take output from Salesforce & transform it to a json. here is my code:
%dw 1.0
%output application/json
payload map {
headerandlines:{ id : $.Id,
agreementLineID : $.LineItems__r.Id,
netPrice : $.LineItems__r.Price__c,
volume : $.Volume__c,
name : $.Name,
StartDate : $.Start_Date__c,
EndDate : $.End_Date__c,
poField : $.PO_Field__c,
ConsoleNumber : $.Console_Number__c,
Term : $.Term__c,
ownerID : $.OwnerId,
Unit : $.Unit__c,
siteNumber : $.Site_Num__c,
customerNumber : $.Customer_Num__c
}
}
input payload looks like this.. it is a collection of objects. Somehow after the transformation only the first object is sent & rest is clobbered.
[
{
"id": "DA0YAAW",
"LineID": [
"jGEAU",
"jBEAU",
"j6EAE"
],
"Price": [
"50000.0",
"12000.0",
"45000.0"
],
"netPrice": null,
"volume": null,
"name": " Test 2.24",
"StartDate": "2017-02-17",
"EndDate": "2018-02-17",
"poField": "123456",
"ConsoleNumber": "8888888",
"PaymentTerm": "thirty (30)",
"ownerID": “abcd”,
"OperatingUnit": " International Company",
"siteNumber": null,
"customerNumber": null
},
{
"id": "a37n0000000DAMAAA4",
"LineID": [
"JunEAE",
"JuiEAE",
"KdMEAU",
"JuYEAU"
],
"Price": [
"5000.0",
"8000.0",
"5000.0",
"5000.0"
],
"netPrice": null,
"volume": null,
"name": " Test 3.6",
"StartDate": "2017-03-06",
"EndDate": "2018-03-16",
"poField": "12345",
"ConsoleNumber": "123456-",
"PaymentTerm": "30 NET",
"ownerID": “dfgh”,
"OperatingUnit": ", inc.",
"siteNumber": null,
"customerNumber": null
},
….
]
When I call this code from the browser (using API testing) I get the complete payload with multiple objects. When I call this from another API I get only one 1 object indicating it is not looping through. I can confirm that the payload has multiple objects . Is there anything I am missing in terms of looping through this code to extract multiple objects? I assume that '$' notation is good enough for iteration.
#insaneyogi, your input is either incorrect or your dataweave is incorrect.
Here in the input you have specified id in the small. but in dataweave, it is mentioned in capital.
I think the problem here is with your Lineitem and Price type elements. They are collection within and element. In your data mapping $. will take care of the outer object. However, i think the mapping like LineItems__r.Price__c is not correct. It should have proper index , probably LineItems__r.Price__c[0]. Please try that and it should work. First change the input with single element for price or line-item and test.
It looks like the agreementLineID and netPrice are arrays and you need to loop through them with a map operator within the bigger outer map to get all the line items. That should work.

How to get unnamed object instead of an array in case of only one result in Dataweave

We have a transformation with Dataweave which processes a list of objects. We get a json response like that:
{"hotels": [{
"name": "Hotel Oslo",
"propertyCode": "12345",
"currency": "NOK"
},
{
"name": "Hotel Stockholm",
"propertyCode": "12346",
"currency": "SEK"
}]}
However, in the case of only 1 response, we want to have the following response:
{"name": "Hotel Stockholm",
"propertyCode": "12346",
"currency": "SEK"}
We are generating the response like this:
{
hotels: payload.rows map ((row , indexOfRow) -> {
name: row.content.companyName.content,
propertyCode: row.content.propertyCode.content,
currency: row.content.currencyCode.content
})}
What should we put as a condition so that we do not get an array in case of 1 result?
Try this:
%dw 1.0
%output application/json
%function makeHotel(row) {
name: row.name,
propertyCode: row.propertyCode,
currency: row.currency
}
---
{
hotels: payload.rows map ((row , indexOfRow) -> makeHotel(row))
} when ((sizeOf payload.rows) != 1)
otherwise makeHotel(payload.rows[0])
It will give you an empty array on empty input, the simple object for one input and the structure with array when you have more than one input row.
(For test purposes, with a slightly differnt input structure, but the general solution should be clear.)

How to get list of statements for a given Wikidata ID?

The only thing I managed to do is this link:
https://www.wikidata.org/w/api.php?action=wbgetentities&ids=Q568&format=jsonfm
But this produces lots of useless data. What I need is to get all the statements for the given item, but I can't see any of the statements in the query above.
here it will be:
{ "instance of" : "chemical element",
"element symbol" : "Li",
"atomic number" : 3,
"oxidation state" : 1,
"subclass of" : ["chemical element", "alkali metal"]
// etc...
}
Is there an API for this or must I scrape the web page?
The information you want is in your query, except it's hard to decode. For example, this:
"P246": [
{
"id": "q568$E47B8CE7-C91D-484A-9DA4-6153F132997D",
"mainsnak": {
"snaktype": "value",
"property": "P246",
"datatype": "string",
"datavalue": {
"value": "Li",
"type": "string"
}
},
"type": "statement",
"rank": "normal",
"references": …
}
]
means that the “element symbol” (property P246) is “Li”. So, you will need to read all the properties from your query and then find out the name for each of the properties you found.
To get just the statements, you could also use action=wbgetclaims, but it's in the same format as above.