I have a For Each controller in Jmeter, which iterates a list of complex JSON objects, for example:
JSONObject{
"field1": "value1",
"field2": "value2",
"field3": "value3"
}
during iterations I'm able to access the current complex object with for each, but I can't access inner values: I need to access to field1, field2 values.
Anyone can help?
You can do it using i.e. JSR223 PreProcessor and Groovy language:
def field1 = new groovy.json.JsonSlurper().parseText(vars.get('your-variable')).field1
vars.put('field1', field1)
or using __groovy() function:
${__groovy(new groovy.json.JsonSlurper().parseText(vars.get('your-variable')).field1,)}
More information:
JsonSlurper
Apache Groovy - Parsing and producing JSON
Apache Groovy: What Is Groovy Used For?
Related
I have a JSON response below:
"books": [
{
"name" : "test1",
"id" : "T01"
},
{
"name" : "test2",
"id" : "T02"
},
{
"name" : "test3",
"id" : "T03"
},
]
I am extracting all respective ids and sending it as a body to another request.
Other request takes it as an array of strings but when I am extracting it, it is showing as integers:
Currently it shows: ids_ALL = [T01, T02, T03]
and I have to pass it like: ids_ALL = ["T01", "T02", "T03"]
Note: I am suffixing _ALL to get all ids.
Since it is not passing the array as string, I am getting an error.
Is there away to extract it and put it in array of strings or way to use post-processer and then convert the array and send to other request.
This one-liner will extract all the IDs and generate the JSON Array you're looking for:
vars.put('payload', (new groovy.json.JsonBuilder(new groovy.json.JsonSlurper().parse(prev.getResponseData()).books.id.collect()).toPrettyString()))
no other extractors are needed, you can refer the generated array as ${payload} later on where required
In Taurus it can be put into the JSR223 Block
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It
You can use JSON Extractor or JSON JMESPath Extractor to extract all the ids from the response.
Place a JSR223 Post processor just below the JSON Path Extractor to create a list of Strings (ids)
def idCount=vars.get("booksIds_matchNr").toInteger()
def lstIds=[]
for(i in 1..idCount){
String currentId=vars.get("booksIds_" + i)
lstIds.add("\""+ currentId + "\"" )
//lstIds.add("${currentId}" )
}
vars.putObject("lstIds",lstIds)
You can access the list with vars.getObject("lstIds")
List of strings could be seen in the view result tree.
Another quick solution
Add a JSR223 Post Processor below the JSON Extractor to create strings with the available values.
String booksIds_ALL=vars.get("booksIds_ALL")
def lstIds = "\"" + booksIds_ALL.replace(",", "\",\"") + "\""
vars.putObject("lstIds",lstIds)
In just starting to use JMeter I am trying to set variables of the form taskId_1, taskId_2, taskId_3 (defined in "User Defined Variables") and use them in HTTP Samples (REST requests). When I run postprocessors none of my JSON Extractors or Regular Expression Extractors save the values matched (and I tested the extracted regular expression using RegExp tester.)
The response sent from the GET request that I am parsing looks like (edited for readability):
{
"case-data": {
"Description": "100 parallel tasks",
"Workflow": {
"com.MyCompany": {
"workflow-case-id": null,
"stages": [
{
"stage-guid": "470D2E00-A9E1-11EB-887B-4226FC2CA371",
"tasks": [
{
"task-name": "Stage1Task1P",
"user-group-id": "Joe",
"task-id" : 52
},
{
"task-name": "Stage1Task2P",
"user-group-id": "Joe",
"task-id" : 73
},
{
"task-name": "Stage1Task3P",
"user-group-id": "Joe",
"task-id" : 123
}
]
} ] }}}}
Following the BlazeMeter tutorials, for the Regular Expression Extractor I use
Apply To "Main sample and sub-samples"
Field to check "Response Message"
Name of created variable taskId
Regular expression task-id"\ :\ (.\d+)$
$1$
(I have also tried taskId_1 - my ideal solution would set all the taskId's at once).
For the JSON Extractor that I just tried I use:
Names of created variables: taskId
JSON Path Expressions: $."task-id" (LOG ALL indicates Could not find JSON Path - so I will revise)
Match No: -1
Default Values: taskId not matched
It is as if none of these strings are ever matched so the values are not set - not even default values. I also have a Debug Sample, Debug Postprocessor and a View Results Tree included in the parent Logic Controller - but see no values of variables set anywhere (even in the logs).
I have other JSON extractors that attempt to traverse down the object tree from the top but they also are not setting my User Variables although LOG ALL indicates they are setting the variables of the same name.
What is wrong with my match expressions and assignment parameters?
How can I change my usage of Debug Sampler/Postprocessor/View Result Tree/Properties and variable viewer (which has JMeter variables = True) to observe variables?
Is there a way to run a test plan one step at a time (e.g., a preprocessor, a request, a postprocessor then another postprocessor) by clicking on UI elements?
Regular Expression Extractor:
"task-id"\s*:\s*(\d+)
More information: JMeter Regular Expressions
JSON Extractor:
$..task-id
More information: Jayway JsonPath
To view generated variables just add a Debug Sampler somewhere at the bottom of your script and add View Results Tree listener so Debug Sampler would be in its scope, see How to Debug your Apache JMeter Script for more details.
I have strange case for jmeter. Imagine that we have an json array with elements like this:
{
"id" : 123456,
"name": "TEST"
}
So I want to get random element from array that has id. For this case I use Json Path PostProcessor with expression like this $.elements[?(#.id)]
But for some reasons I need an index of this element. So I can create BeanShellPostProcessor generate random index and then use same Json Path PostProcessor with expression like this $.elements[${PARAM_ElementIndex}].
But in some cases this array can be empty and Json Path PostProcessor wil fail with exception like this:
jmeter.extractor.json.jsonpath.JSONPostProcessor: Error processing JSON content in PARAM_ResumeId, message:No results for path: $['elements'][0]['id']
So may be someone can suggest any solution
I would recommend use Groovy instead of Beanshell as:
Well-behaved Groovy scripts can be compiled into bytecode therefore performance will be much higher
Groovy has built-in JSON support
So given you have JSON Response like:
{
"elements": [
{
"id": 123456,
"name": "TEST"
},
{
"id": 7890,
"name": "TEST2"
}
]
}
You can extract random ID along with its index using the following example Groovy code in the JSR223 PostProcessor:
import groovy.json.JsonSlurper
import java.util.concurrent.ThreadLocalRandom
String response = prev.getResponseDataAsString()
def jsonSlurper = new JsonSlurper()
def json = jsonSlurper.parseText(response)
int size = json.elements.size
if (size > 0){
def randomIndex = ThreadLocalRandom.current().nextInt(size)
def value = json.elements.get(randomIndex).id
log.info('Index: ' + randomIndex)
log.info('Value: ' + value)
}
Demo:
References:
Parsing and producing JSON
Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For!
I am working on a POST service that give JSON response.
I have to extract certain value from the JSON response. example-
`{
"Result":
{ "Id":22
"StartTime":
"EndTime":
"RoutePoints":
[{ "Id":675,
}
{ "Id":676,
}
]
}
} `
My first part of the question-
How do I refer the "Id" variable inside the "RoutePoint" array using regular expression extractor? I can simply use "Id", but I also have an "Id" variable outside the "RoutePoint" array.
Secondly-
How do I take the "Id" each time and run them in a loop in the following service? Example- I take "Id=675" and perform a job, then take "Id=676" and perform that same job. Please be as detailed as possible, I am new to JMeter.
I would recommend going for JSON Path PostProcessor which is available since JMeter 3.0
Add JSON Path PostProcessor as a child of the request which returns above JSON and configure it as follows:
Variable Names: anything meaningful, i.e. Id
JSON Path Expressions: $..RoutePoints.*.Id
Match Numbers: -1
You should get variables like:
Id_1=675
Id_2=676
Id_matchNr=2
suitable for iteration with i.e. ForEach Controller
Demo:
References:
JSONPath - XPath for JSON
Advanced Usage of the JSON Path Extractor in JMeter
I am using Jmeter for performance testing and stuck at following point:
I am getting a JSON response from Webapi as follows:
PersonInfoList:
Person
[0]
{
id: 1
name: Steve
}
[1]
Person
{
id: 2
name: Mark
}
I need to get the ids based on the count of this JSON array and create a comma separated string as ("Expected value" = 1,2)
I know how to read a particular element using JSON Post processor or Regex processor but am unable to loop through the array and create a string as explained so that I can use this value in my next sampler request.
Please help me out with this: I am using Jmeter 3.0 and if this could be achieved without using external third party libs that would be great. Sorry for the JSON syntax above
Actually similar functionality comes with JSON Path PostProcessor which appeared in JMeter 3.0. In order to get all the values in a single variable configure JSON Path PostProcessor as follows:
Variable Names: anything meaningful, i.e. id
JSON Path Expressions: $..id or whatever you use to extract the ids
Match Numbers: -1
Compute concatenation var (suffix _ALL): check
As a result you'll get id_ALL variable which will contain all JSON Path expression matches (comma-separated)
More "universal" answer which will be applicable for any other extractor types and in fact will allow to concatenate any arbitrary JMeter Variables is using scripting (besides if you need this "expected value and parentheses)
In order to concatenate all variables which names start with "id" into a single string add Beanshell PostProcessor somewhere after JSON Path PostProcessor and put the following code into "Script" area
StringBuilder result = new StringBuilder();
result.append("(\"Expected value\" = ");
Iterator iterator = vars.getIterator();
while (iterator.hasNext()) {
Map.Entry e = (Map.Entry) iterator.next();
if (e.getKey().matches("id_(\\d+)")) {
result.append(e.getValue());
result.append(",");
}
}
result.append(")");
vars.put("expected_value", result.toString());
Above code will store the resulting string into ${expected value} JMeter Variable. See How to Use BeanShell: JMeter's Favorite Built-in Component article for more information regarding bypassing JMeter limitations using scripting and using JMeter and Java API from Beanshell test elements.
Demo: