Dynamically fetching the Json key value in Lua - arrays

I have an input Json for which I need to get the value for a specific key. Key name will be dynamic and will be passed in input like below -
Input Json -
{
"error": "Bad Request"
"source": [
{
"code": "400",
"message": "Missing values"
}
]
}
Here I need to get the value for code and message dynamically. I am able to read the values if I give the path directly like below -
json_body["source"][1].code
But here json path will be passed by user in input as string like below -
local path = "source[1].code"
How can I use this path variable value and get the Json value for this key. I tried below but its not working -
json_body[path]
Below is the sample Lua code which I am using -
local cjson = require("cjson.safe").new()
local function read_json_body(body)
if body then
return cjson.decode(body)
end
end
local json_body = read_json_body(buffered_data)
local message_path = "source[1].code"
local value = json_body[message_path]
I am able to get the values for the fields which are outside of array like below -
local message_path = "error"
local value = json_body[message_path]

As suggested by #EgorSkriptunoff below code worked -
local value = assert(load("return "..path, nil, "t", json_body))()

Related

How to extract data from an API and create an array to send to the another API in Jmeter?

Example:
API A:
{
"customer":[
{
"name":"Jane",
"phone":"9999999",
"email":"jane#test.com"
},
{
"name":"John",
"phone":"8888888",
"email":"john#test.com"
},
{
"name":"Joe",
"phone":"7777777",
"email":"Joe#test.com"
}
]
}
Using the JSON extractor, I want to get the names of all the customers
so: Jane, John, Joe
How do I get these values and turn them into an array
[{"name":"Jane", "name":"John", "name":"Joe"}]
And pass it onto the next API?
Note: That it has to be dynamic so API A could show different 2 names or 1 name or more and needs to be adjusted into the array
First of all your [{"name":"Jane", "name":"John", "name":"Joe"}] is not a valid JSON, you can check it yourself:
so I strongly doubt that this is the string you need to generate.
So if you really need to construct this value you can do something like:
Add JSR223 PostProcessor as a child of the request which returns this "customers" data
Put the following code into "Script" area:
def response = new groovy.json.JsonSlurper().parse(prev.getResponseData())
def payload = new StringBuilder()
payload.append('[{')
0.upto(response.customer.size - 1, { index ->
payload.append('"name": "').append(response.customer[index].name).append('"')
if (index != response.customer.size - 1) {
payload.append(',')
}
})
payload.append('}]')
vars.put('payload', payload as String)
Refer the generated value as ${payload} where required
Demo:
More information:
JsonSlurper
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It

How to store array values in an environment variable in Postman

I am using a postman to automate apis.
Now I am using following request , lets say :-
{
"customerId": "{{currentClientId}}"
}
Where clientid is a dynamic variable whose value is substituted dynamically as 1 , 2, 3,4 so on..
I call this request multiple times using setNextRequest call in this eg lets say 10.This is being done using a counter variable. I am initialising the counter in my previous request to 0 and using for loop with value as counter as 10 calling the request 10 times.There is no response in body just successful http code 204.
I want to store all these clientids coming in request into an environment Client array variable so I wrote a following pre-request script:-
counter = pm.environment.get("counter");
ClientArray = pm.environment.get("ClientArray");
ClientArray.push(pm.environment.get("currentClientId"));
pm.environment.set("ClientArray",ClientArray);
In Test Script, wrote following code :-
counter = pm.environment.get("counter");
if(counter<=10) {
console.log("hi");
postman.setNextRequest("Request");
counter++;
pm.environment.set("counter",counter);
console.log("Counter",counter);
}
The above scipts is throwing
TypeError | ClientArray.push is not a function.
Could someone please advice how to achieve this.
When you retrieve a value from an environment variable like you're doing:
ClientArray = pm.environment.get("ClientArray");
You're not getting an array, you're getting a string which is why you're getting that error. You need to treat the variable like a string, append the currentClientId much like you do for the counter. Something like:
var currentClientIds = pm.environment.get("ClientArray");
currentClientIds = currentClientIds + "," + currentClientId
When you're done appending i.e. out of your loop simply take the string and convert it to an array:
var currentClientIds = pm.environment.get("ClientArray");
var idsArr = curentClientIds.split(',');

Getting values from json array using an array of object and keys in Python

I'm a Python newbie and I'm trying to write a script to extract json keys by passing the keys dinamically, reading them from a csv.
First of all this is my first post and I'm sorry if my questions are banals and if the code is incomplete but it's just a pseudo code to understand the problem (I hope not to complicate it...)
The following partial code retrieves the values from three key (group, user and id or username) but I'd like to load the objects and key from a csv to make them dinamicals.
Input json
{
"fullname": "The Full Name",
"group": {
"user": {
"id": 1,
"username": "John Doe"
},
"location": {
"x": "1234567",
"y": "9876543"
}
},
"color": {
"code": "ffffff",
"type" : "plastic"
}
}
Python code...
...
url = urlopen(jsonFile)
data = json.loads(url.read())
id = (data["group"]["user"]["id"])
username = (data["group"]["user"]["username"])
...
File.csv loaded into an array. Each line contains one or more keys.
fullname;
group,user,id;
group,user,username;
group,location,x;
group,location,y;
color,code;
The questions are: can I use a variable containing the object or key to be extract?
And how can I specify how many keys there are in the keys array to put them into the data([ ][ ]...) using only one line?
Something like this pseudo code:
...
url = urlopen(jsonFile)
data = json.loads(url.read())
...
keys = line.split(',')
...
# using keys[] to identify the objects and keys
value = (data[keys[0]][keys[1]][keys[2]])
...
But the line value = (data[keys[0]][keys[1]][keys[2]]) should have the exact number of the keys per line read from the csv.
Or I must to make some "if" lines like these?:
...
if len(keys) == 3:
value = (data[keys[0]][keys[1]][keys[2]])
if len(keys) == 2:
value = (data[keys[0]][keys[1]])
...
Many thanks!
I'm not sure I completely understand your question, but I would suggest you to try and play with pandas. It might be as easy as this:
import pandas as pd
df = pd.read_json(<yourJsonFile>, orient='columns')
name = df.fullname[0]
group_user = df.group.user
group_location = df.group.location
color_type = df.color.type
color_code = df.color.code
(Where group_user and group_location will be python dictionaries).

Regex to match the last value in given data

I get data from a URL, and am working on the data to check for a few conditions. The data from the URL look like this:
1528190345":100,"1528190346":100,"1528190368":100,"1528190414":100,"1528190439":99,"1528190440":99,"1528190463":100,"1528190485":100,"1528190508":100,"1528190550":100,"1528190575":100,"1528190576":100,"1528190599":100,"1528190600":100,"1528190622":100,"1528190667":100,"1528190688":100,"1528190689":100,"1528190712":100,"1528190736":100,"1528190762":100,"1528190785":100,"1528190786":100,"1528190807":100,"1528190828":100,"1528190853":100,"1528190877":100,"1528190901":100,"1528190925":100,"1528190948":100,"1528190968":100,"1528190991":100}}]
====
I have converted that too JSON
{"metric"=>"Insta_real-unique_value", "tags"=>{"host"=>"letme.quickly.com", "tier"=>"2", "device"=>"tester1", "dc"=>"xxx"}, "aggregateTags"=>["device_name", "device_ip"], "dps"=>{"1526972408"=>100, "1526972424"=>100, "1526972440"=>100, "1526972456"=>100, "1526972472"=>100, "1526972488"=>100, "1526972504"=>100, "1526972520"=>100, "1526972536"=>100, "1526972552"=>100, "1526972568"=>100, "1526972569"=>100, "1526972584"=>100, "1526972585"=>100, "1526972601"=>100, "1526972617"=>100, "1526972633"=>100, "1526972649"=>100, "1526972665"=>100, "1526972681"=>100}}
I want to extract the value that corresponds to 100. When I do this:
url = "#{URL}"
uri = URI(url)
response = Net::HTTP.get(uri)
value = response[-6..-4]
puts value
I get the last value, but when the last value changes to 99/9/0, it prints :99 or ":9.
Is there a way to get the exact value as is?
When dealing with JSON data, it's almost always better to parse the data properly rather than using regex against the string.
In this case, we can do:
JSON.parse(response)['dps'].values.last #=> 100
If the response is a json response, you must use a json parser else if is not a json response, you can use a regex expression with a Regex Object.
In case of a json response, assuming that the object is something like is declared into the variable response of the next code, you can parse it into a JObject. (using Newtonsoft.Json available from nuget repository).
See the next example :
string response = "[{\"response\":{\"1528190345\":100,\"1528190346\":100,\"1528190368\":100,\"1528190414\":100,\"1528190439\":99,\"1528190440\":99,\"1528190463\":100,\"1528190485\":100,\"1528190508\":100,\"1528190550\":100,\"1528190575\":100,\"1528190576\":100,\"1528190599\":100,\"1528190600\":100,\"1528190622\":100,\"1528190667\":100,\"1528190688\":100,\"1528190689\":100,\"1528190712\":100,\"1528190736\":100,\"1528190762\":100,\"1528190785\":100,\"1528190786\":100,\"1528190807\":100,\"1528190828\":100,\"1528190853\":100,\"1528190877\":100,\"1528190901\":100,\"1528190925\":100,\"1528190948\":100,\"1528190968\":100,\"1528190991\":100}}]";
List<Dictionary<string, Dictionary<string, int>>> values = JsonConvert.DeserializeObject<List<Dictionary<string, Dictionary<string, int>>>>(response);
Dictionary<string, Dictionary<string, int>> firstLevel = values[0]; // Access to the first object of the list closed with ']'
Dictionary<string, int> secondLevel = firstLevel["response"]; // Access to the first object response and get's it's object context of first '}' starting from the end of response
/** This is an option, if you ever knows the name of the element (1528190991) */
int thirdLevel = secondLevel["1528190991"]; // Access to the last element of the object by it's name, context of second '}' starting from the end of response.
Console.WriteLine(thirdLevel);
/** This is another option if you doesn't know the name of the element and wants ever the last element. */
List<int> listOfValues = secondLevel.Values.ToList();
Console.WriteLine(listOfValues[listOfValues.Count-1]);
Note that i've chenged a little bit your response adding [{\"response\":{\" at the start to become a json response.
If is not a json response you can use this pattern with regular expression :
:(.{2,6})}}\]$
Hope will help!

Accessing json generated by stringify

I have an array in which data from db is stored. I have converted this array into JSON by stringify which results in json like this:
var view_data = [{ f o o = " boo " , t e x t = "t e s t " }];
When i try to access this foo object via for loop like this :
for(var d=0; d<view_data.length; d++)
{
print view_data[d].foo;
}
It gives undefined. I think this is not actually json object is array of strings.
Please help me to access the key-value pair.
You seem to be fuzzy on the meaning of JSON. JSON is a string-based format used for exchanging data. It's not used, and is irrelevant, in the course of normal programming in JavaScript, unless you're sending data to somewhere, or receiving data from somewhere, in JSON format.
I have converted this array into JSON by stringify which results in json like this:
var view_data = [{ f o o = " boo " , t e x t = "t e s t " }];
JSON.stringify takes a JavaScript object and converts it into a string-based format. Therefore this is impossible. JSON.stringify would always return a string, not a (broken) JS object as you have shown.
In your sample data, you have shown extra spaces in the property names: "f o o" instead of "foo". If in fact that's how you have attempted to specify your JS object, it won't work at all. It's invalid syntax. It is also invalid syntax to use an equal sign; you need a colon.
If you define your JS object correctly, then the code you showed will work fine:
var view_data = [{foo: "boo" , text: "test"}];
for (var d=0; d<view_data.length; d++) {
print view_data[d].foo;
}
Accessing json generated by stringify
You don't access JSON generated by stringify. JSON is a string format meant only use in communicating with some external system.
how should then access the array as json object
There is no such thing as a JSON object. There is JSON, which is a string; and there are JavaScript objects.
For more information on JavaScript objects vs. JSON, see How to parse variables to JSON Object (Javascript).

Resources