In Gatling, how to iterate json array in .check to validate all values - gatling

Sample Json Response is
{
"data": {
"types": [
{
"attributes": [
{
"body": {
"id": 123
}
},
{
"body": {
"id": 456
}
}
]
},
{
"attributes": [
{
"body": {
"id": 456
}
},
{
"body": {
"id": 123
}
}
]
}
]
}
}
I want to validate that all id's are 123, if values are other than 123 Gatling test should fail.
I have tried below code it's failing in assertion but gatling report is showing passed. As I guess assert is a juint assert and not gatling assert.
val testSC1 = scenario("Sample-test")
.exec(http("Test-Post")
.post("dataservice/v1/test")
.header("Authorization", getToken)
.body(StringBody(getPayload))
.asJSON
.check(jsonPath("$.data.types[*].attributes[*].body.id").findAll.saveAs("getAllId"))
).
exec
{ session =>
//println(session("getAllId").as[String])
val iDs = session("getAllId").as[Seq[String]]
for (getEachId <- iDs)
{
assert(getEachId.equals("123"),"Actual: "+getEachId+"Expected : 123")
}
session
}
How do I iterate values in .check method
$.data.types[].attributes[].body.id ?
Or any other better solution will be helpful.

jsonPath("$.data.types[*].attributes[*].body.id").findAll.is(Seq("expectedValue1", "expectedValue2", "expectedValue3"))

Related

JSON dot notation returning different from JSON api request [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 14 days ago.
Using dot notation to access a JSON response is returning different values than what the API response is saying in my browser
I tried to access a JSON response from an axios request like so:
const response = await axios.get('https://store-site-backend-static.ak.epicgames.com/freeGamesPromotions?locale=en-US&country=US&allowCountries=US');
console.log(response.data.data.Catalog.searchStore.elements.promotions)
Instead of getting a response something similar to this in JSON:
{
"promotions": {
"promotionalOffers": [
{
"promotionalOffers": [
{
"startDate": "2023-02-02T16:00:00.000Z",
"endDate": "2023-02-09T16:00:00.000Z",
"discountSetting": {
"discountType": "PERCENTAGE",
"discountPercentage": 0
}
}
]
}
],
"upcomingPromotionalOffers": []
}
}
I simply get this from the console log:
undefined
undefined
undefined
undefined
undefined
I might not be using dot notation to access it correctly but I have no idea. You can view the JSON response from the browser here: https://store-site-backend-static.ak.epicgames.com/freeGamesPromotions?locale=en-US&country=US&allowCountries=US
#1 Getting data from the server by axios.
The elements start [ and end ] is an array data.
(* I copy/paste from Browser to VS code after access URL, saved JSON data)
VS code can expand/collapse data by clicking down arrow.
#2 Filter only promotions
It is one of Key values of array elements
You can filter by Array map()
Simple example for getting title only
const titles = elements.map(item => { return { title : item.title } } )
console.log(JSON.stringify(titles, null, 4))
[
{
"title": "Borderlands 3 Season Pass"
},
{
"title": "City of Gangsters"
},
{
"title": "Recipe for Disaster"
},
{
"title": "Dishonored®: Death of the Outsider™"
},
{
"title": "Dishonored - Definitive Edition"
}
]
So this code will works for getting promotions
const axios = require('axios')
const getPromotions = async (data) => {
try {
const response = await axios.get('https://store-site-backend-static.ak.epicgames.com/freeGamesPromotions?locale=en-US&country=US&allowCountries=US');
return Promise.resolve(response.data)
} catch (error) {
return Promise.reject(error)
}
};
getPromotions()
.then(result => {
const promotions = result.data.Catalog.searchStore.elements.map(item => { return { promotions : item.promotions } } )
console.log(JSON.stringify(promotions, null, 4))
})
.catch(error => {
console.log(error.message)
});
Result
$ node get-data.js
[
{
"promotions": {
"promotionalOffers": [
{
"promotionalOffers": [
{
"startDate": "2023-01-26T16:00:00.000Z",
"endDate": "2023-02-09T16:00:00.000Z",
"discountSetting": {
"discountType": "PERCENTAGE",
"discountPercentage": 30
}
},
{
"startDate": "2023-01-26T16:00:00.000Z",
"endDate": "2023-02-09T16:00:00.000Z",
"discountSetting": {
"discountType": "PERCENTAGE",
"discountPercentage": 30
}
}
]
}
],
"upcomingPromotionalOffers": []
}
},
{
"promotions": {
"promotionalOffers": [
{
"promotionalOffers": [
{
"startDate": "2023-02-02T16:00:00.000Z",
"endDate": "2023-02-09T16:00:00.000Z",
"discountSetting": {
"discountType": "PERCENTAGE",
"discountPercentage": 0
}
}
]
}
],
"upcomingPromotionalOffers": []
}
},
{
"promotions": {
"promotionalOffers": [],
"upcomingPromotionalOffers": [
{
"promotionalOffers": [
{
"startDate": "2023-02-09T16:00:00.000Z",
"endDate": "2023-02-16T16:00:00.000Z",
"discountSetting": {
"discountType": "PERCENTAGE",
"discountPercentage": 0
}
}
]
}
]
}
},
{
"promotions": {
"promotionalOffers": [
{
"promotionalOffers": [
{
"startDate": "2023-02-02T16:00:00.000Z",
"endDate": "2023-02-09T16:00:00.000Z",
"discountSetting": {
"discountType": "PERCENTAGE",
"discountPercentage": 0
}
}
]
}
],
"upcomingPromotionalOffers": []
}
},
{
"promotions": null
}
]

How to filter JSON data based on another JSON data in typescript

I have 2 JSON Data 1. Payers 2. Rules. I need to filter Payers JSON data based on PayerId from Rules JSON data.
{
"Payers": [
{
"payerId": "12345",
"name": "Test Payer1"
},
{
"payerId": "23456",
"name": "Test Payer2",
},
{
"payerId": "34567",
"name": "Test Payer3"
}}
Rules JSON file
{
"Rules": [
{
"actions": {
"canCopyRule": true
},
"RuleId": 123,
"description": "Test Rule",
"isDisabled": false,
"Criteria": [
{
"autoSecondaryCriteriaId": 8888,
"criteriaType": { "code": "primaryPayer", "value": "Primary Payer" },
"payerId": ["12345", "34567"]
}
]
}
}]}
I need to filter Payers JSON data based on Rules JSON data if PayerID matches
I need output like below
{
"Payers": [
{
"payerId": "12345",
"name": "Test Payer1"
},
{
"payerId": "34567",
"name": "Test Payer3"
}
}
How to filter?
You can use Array.filter like that (based on your data structure):
const filteredPayers = payersObj.Payers.filter((p) => rulesObj.Rules[0].Criteria[0].payerId.includes(p.payerId));
I can't figure out why your Rules json looks like this, I guess you have multiple rules. If so, you will need to iterate over each rule and invoke includes. Same for Criteria.
Code will check each rule and each critirias
and will return payers if payerId found in any of the given rules of any criteria
const payers = {
"Payers": [
{
"payerId": "12345",
"name": "Test Payer1"
},
{
"payerId": "23456",
"name": "Test Payer2",
},
{
"payerId": "34567",
"name": "Test Payer3"
}]}
const rules = {
"Rules": [
{
"actions": {
"canCopyRule": true
},
"RuleId": 123,
"description": "Test Rule",
"isDisabled": false,
"Criteria": [
{
"autoSecondaryCriteriaId": 8888,
"criteriaType": { "code": "primaryPayer", "value": "Primary Payer" },
"payerId": ["12345", "34567"]
}
]
}
]
}
const data = payers.Payers.filter(payer => rules.Rules.findIndex(rule => rule.Criteria.findIndex(criteria => criteria.payerId.includes(payer.payerId)) != -1) !== -1)
console.log(data)

How can i filter the un matched array elements alone when compare with another array objects in angular 8

I have a two array response and I would like to compare the two responses and have to filter the unmatched array elements into a new array object.
Condition to compare the two response and filter is: we have to filter when code and number are not matched exactly with the response two then we have to filter such an array element into a new array object which I need as an output.
The Array element present in the Response two example is also present in the Response of Array One example which I don't want and I need to filter the array elements which is not matched with the Response of Array One.
Final Output which we filtered from the response two array will be like below which is unmatched with the response 1 array object:
{
"unmatchedArrayRes": [
{
"code": "08",
"number": "2323232323",
"id": "432",
"value": "value432"
}
]
}
Response of Array One
{
"MainData": [
{
"DataResponseOne": [
{
"viewData": {
"number": "11111111111111",
"code": "01"
},
"name": "viewDataOne"
},
{
"viewData": {
"number": "22222222222222",
"code": "01"
},
"name": "viewDataTwo"
},
{
"viewData": {
"number": "3333333333333",
"code": "02"
},
"name": "viewDataThree"
}
]
},
{
"DataResponseTwo": [
{
"viewData": {
"number": "5555555555555",
"code": "9090"
},
"name": "viewDataFour"
},
{
"viewData": {
"number": "6666666666666",
"code": "01"
},
"name": "viewDataFive"
},
{
"viewData": {
"number": "8888888888888",
"code": "01"
},
"name": "viewDataSix"
}
]
}
]
}
Response Two Example :
{
"compareRes": [
{
"code": "01",
"number": "11111111111111",
"id": "123",
"value": "value123"
},
{
"code": "9090",
"number": "5555555555555",
"id": "345",
"value": "value567"
},
{
"code": "08",
"number": "2323232323",
"id": "432",
"value": "value432"
}
],
"metaData": "343434343434"
}
First, create a combined list of all the view items from response one.
const combinedList = [];
res1["MainData"].forEach(data => {
// console.log(data);
for( let key in data) {
// console.log(key);
data[key].forEach(innerData => {
console.log(innerData)
combinedList.push(innerData["viewData"]);
})
}
});
In the above method, It is done in such a way that it can handle multiple viewData responses like DataResponseOne, DataResponseTwo, and so on.
And then filter second response Items like this:
const unfilteredListItems = res2["compareRes"].filter(data => {
return !combinedList.some(listItem => {
return listItem.code === data.code && listItem.number === data.number;
});
});
console.log(unfilteredListItems);
Working Stackblitz link: https://stackblitz.com/edit/ngx-translate-example-aq1eik?file=src%2Fapp%2Fapp.component.html

Logic App - Refer and map fields on different JSON data sources

I have two JSON data sources:
Source Data 1:
{
"result": [
{
"resource_list": "7961b907db9253045fbdf1fabf9619d4,55617907db9253045fbdf1fabf9619d2",
"project": "11216",
"project_manager": {
"value": "55617907db9253045fbdf1fabf9619d2"
}
}
]
}
Source Data 2:
{
"result": [
{
"sys_id": "7961b907db9253045fbdf1fabf9619d4",
"email": "test.user1#mysite.com"
},
{
"sys_id": "55617907db9253045fbdf1fabf9619d2",
"email": "test.user2#mysite.com"
}
]
}
I want to reference "resource_list" and "project_manager" from Source Data 1 to "sys_id" in Source Data 2 and get "email" out from Source Data 2 and then compose a final Output like below:
Output:
[
{
"__metadata":
{
"uri": "ProjectCode"
},
"externalProject": "11216",
"projectCodeAssignment":
[
{
"__metadata":
{
"uri": "projectCodeAssignment"
},
"externalProjectAssignee": "test.user1#mysite.com"
},
{
"__metadata":
{
"uri": "projectCodeAssignment"
},
"externalProjectAssignee": "test.user2#mysite.com"
}
]
}
]
Is this possible to get this done entirely in Logic App without using Function App or anything to perform it rather.
I write a js script for you. For a quick demo, I omitted some data related to __metadata, seems that is some hard code, not so important here. Try Logic below:
Code in JS code action:
var body = workflowContext.trigger.outputs.body
var data1 = body.data1;
var data2 = body.data2;
var result = [];
data1.result.forEach(item =>{
var resultItem = {};
resultItem.externalProject = item.project;
resultItem.projectCodeAssignment =[];
var resourceIds = item.resource_list.split(',');
resourceIds.forEach(id =>{
var user = data2.result.find( ({ sys_id }) => sys_id === id );
resultItem.projectCodeAssignment.push({"externalProjectAssignee": user.email})
});
result.push(resultItem);
})
return result;
Request Body(your 2 data set are named as data1 and data2 here ):
{
"data1": {
"result": [{
"resource_list": "7961b907db9253045fbdf1fabf9619d4,55617907db9253045fbdf1fabf9619d2",
"project": "11216",
"project_manager": {
"value": "55617907db9253045fbdf1fabf9619d2"
}
}
]
},
"data2": {
"result": [{
"sys_id": "7961b907db9253045fbdf1fabf9619d4",
"email": "test.user1#mysite.com"
}, {
"sys_id": "55617907db9253045fbdf1fabf9619d2",
"email": "test.user2#mysite.com"
}
]
}
}
Result:

Remove elements/objects From Array in ElasticSearch Followed by Matching Query

I'm having issues trying to remove elements/objects from an array in elasticsearch.
This is the mapping for the index:
{
"example1": {
"mappings": {
"doc": {
"properties": {
"locations": {
"type": "geo_point"
},
"postDate": {
"type": "date"
},
"status": {
"type": "long"
},
"user": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
And this is an example document.
{
"_index": "example1",
"_type": "doc",
"_id": "8036",
"_score": 1,
"_source": {
"user": "kimchy8036",
"postDate": "2009-11-15T13:12:00",
"locations": [
[
72.79887719999999,
21.193036000000003
],
[
-1.8262150000000001,
51.178881999999994
]
]
}
}
Using the query below, I can add multiple locations.
POST /example1/_update_by_query
{
"query": {
"match": {
"_id": "3"
}
},
"script": {
"lang": "painless",
"inline": "ctx._source.locations.add(params.newsupp)",
"params": {
"newsupp": [
-74.00,
41.12121
]
}
}
}
But I'm not able to remove array objects from locations. I have tried the query below but it's not working.
POST example1/doc/3/_update
{
"script": {
"lang": "painless",
"inline": "ctx._source.locations.remove(params.tag)",
"params": {
"tag": [
-74.00,
41.12121
]
}
}
}
Kindly let me know where i am doing wrong here. I am using elastic version 5.5.2
In painless scripts, Array.remove() method removes by index, not by value.
Here's a working example that removes array elements by value in Elasticsearch script:
POST objects/_update_by_query
{
"query": {
... // use regular ES query to remove only in relevant documents
},
"script": {
"source": """
if (ctx._source[params.array_attribute] != null) {
for (int i=ctx._source[params.array_attribute].length-1; i>=0; i--) {
if (ctx._source[params.array_attribute][i] == params.value_to_remove) {
ctx._source[params.array_attribute].remove(i);
}
}
}
""",
"params": {
"array_attribute": "<NAME_OF_ARRAY_PROPERTY_TO_REMOVE_VALUE_IN>",
"value_to_remove": "<VALUE_TO_REMOVE_FROM_ARRAY>",
}
}
}
You might want to simplify script, if your script shall only remove values from one specific array attribute. For example, removing "green" from document's .color_list array:
_doc/001 = {
"color_list": ["red", "blue", "green"]
}
Script to remove "green":
POST objects/_update_by_query
{
"query": {
... // use regular ES query to remove only in relevant documents
},
"script": {
"source": """
for (int i=ctx._source.color_list.length-1; i>=0; i--) {
if (ctx._source.color_list[i] == params.color_to_remove) {
ctx._source.color_list.remove(i);
}
}
""",
"params": {
"color_to_remove": "green"
}
}
}
Unlike add(), remove() takes the index of the element and remove it.
Your ctx._source.locations in painless is an ArrayList. It has List's remove() method:
E remove(int index)
Removes the element at the specified position in this list (optional operation). ...
See Painless API - List for other methods.
See this answer for example code.
"script" : {
"lang":"painless",
"inline":"ctx._source.locations.remove(params.tag)",
"params":{
"tag":indexToRemove
}
}
If with ctx._source.locations.add(elt) You add the element, with ctx._source.locations.remove(indexToRemove), you remove by the index of element in the array.

Resources