I have following JSON format in response body
[
{
"Name" : "Prashant",
"City" : "Sydney"
},
{
"Name" : "Yogi",
"City" : "London"
}
]
What is the better way for checking if this array has any records and if yes give me "Name" for first array index. I am using jp#gc JSON extractor plugin for jMeter.
Is it possible to parse this using a plugin or do I need to do it using regular expressions?
Using Ubik Load Pack JSON plugin for JMeter which is part of JMeter since version 3.0 (donated plugin) and called JSON Extractor, you can do it:
Test Plan overview:
ULP_JSON PostProcessor:
If Controller:
And here is the run result:
So as you can see it is possible with plain JMeter
If you're looking to learn JMeter, this book by 3 developers of the project will help you.
I am not sure about your plugin but if it supports JSON path expressions it should be possible.
Try with this expression: $.[0].Name.
This is the plugin I use: http://jmeter-plugins.org/wiki/JSONPathExtractor/ and given expression works with it.
You can find more about JSON Path expressions here: http://goessner.net/articles/JsonPath/index.html#e2.
Working with JSON in JMeter is not quite easy as JMeter was designed long ago before JSON was invented.
There are some extensions however that make life easier:
http://www.ubik-ingenierie.com/blog/extract-json-content-efficiently-with-jmeter-using-json-path-syntax-with-ubik-load-pack/
We can add a regular expression extractor for fetching the value from the response.
Like This:
If possible, always use Regular Expression Extractor. Try to avoid JSON / XPATH / Other extractors. They might look easy to use. But they consume more memory and time. It will affect the performance of your test plan.
source: http://www.testautomationguru.com/jmeter-response-data-extractors-comparison/
Rest Get service sample:
{
"ObjectIdentifiers": {
"internal": 1,
"External1": "221212-12121",
"External3": "",
"Name": "koh"
},
"PartyType": "naturalPerson",
"NaturalPerson": {
"idNo": "221212-12121",
"Title": "Mr",
"Name": "koh",
"FirstName": "",
We had a similar requirement in our project for parsing json responses using jmeter. The requirement was to validate all the fields in the json response and the expected values of field would be provided from external data source.
I found the JSR223 PostProcessor quite usefule in this case as we are able to implement Groovy scripts with this. it comes as a default plugin with the recent Jmeter version
Edit:
Below is the code snippet:
//get the JSON response from prev sampler
String getResponse = prev.getResponseDataAsString();
//parse the response and convert to string
JSONParser parser = new JSONParser(JSONParser.MODE_JSON_SIMPLE);
String parResponse = parser.parse(getResponse);
String preResponse = parResponse.toString();
JsonObject NaturalPerson = JsonObject.readFrom(preResponse);
//replace all commas with a semi-colon
String csvResponse = preResponse.replaceAll(",", ";");
//log response to file
logFileName = "C:/apache-jmeter-5.1.1/Web_Service_Output.csv";
BufferedWriter outLog = new BufferedWriter(new FileWriter(logFileName, true));
outLog.write(csvResponse + "\n");
outLog.close();
Related
I want to extract sys_id for the employee_number does not starting with "C"
{
"items": [{
"sys_updated_on": "2021-01-15 15:04:04",
"sys_id": "60eaa1dc47870d9132f624846d434a",
"employee_number": "C89"
}, {
"sys_updated_on": "2017-12-08 09:26:49",
"sys_id": "c57058e8db8689ca52c4be13961974",
"employee_number": "983"
}, {
"sys_updated_on": "2016-04-08 13:25:00",
"sys_id": "fd413e848716119096ca2d0ebb358e",
"employee_number": "565"
}]
}
I tried multiple JSON Extractor expressions but no luck
$.[?(#.employee_number=~'\d+')].sys_id
$.[?(#.employee_number=~'[0-9]')].sys_id
Need both Xpath and Regular expression combination as the JSON contains many other fields and provided JSON is a small part of that.
I also want to know how to combine the regular expression and JSON
path
If you want to match only numbers in the employee_number - try out the following:
$.items[?(#.employee_number =~ /\d+/)].sys_id
More information:
JsonPath Operators
How to Use the JSON Extractor For Testing
with regards to what you "also want to know" - one post - one question, however I'll give you some hint:
My Response Code Looks like: -
{
"data": {
"transactionId": "04dxf19-xx-42e3-a4f7-75xxa012x4a",
"paymentUrl": "https://wpp-test.wirecard.com/?wPaymentToken=t45QiNvkZX5fYxxxxEEpFz8mcK2ZirBhVMrvuo"
},
"message": "Success.",
"code": "OK",
"appVersion": "2.0.0.47",
"machine": "CHPV345678"
}
and from the above code, I want to extract the value inside = wPaymentToken ( i.e t45QiNvkZX5fYxxxxEEpFz8mcK2ZirBhVMrvuo)
I tried the following options without success -
1) "paymentUrl":
"https://wpp-test.wirecard.com/?wPaymentToken=(.+?)"
2)
wPaymentToken=(.+?)"
Can you please help me , as while checking the value in Debug Sampler it always remains enmpty
Here Is my Test Plan : It contains two REGEX in 1 thread
Here is the reson , why I only want paymentToken because Final URL is not same as the URL that we extracted using JSON
Second option should work fine:
Wouldn't be easier to extract the whole paymentUrl attribute value? It can be done using JSON Extractor with a simple JsonPath expression of $.data.paymentUrl
(Edit: The answer is to use check 'Encode?'option in the HTTP Request. Please see Vinoth's Edit 2 and comment below, thanks!)
This is interesting!
I'm trying to parse a HTTP response which has (let's give concrete example,
bigH:"2a3a6CEH+iJakQpQtPm8efv"
Using Regular Expression Extractor when I try
bigH:"(.+?)"
it extracts the string but replaces all the "+" in the string with space. That is, instead of
"2a3a6CEH+iJakQpQtPm8efv"
it gives me:
"2a3a6CEH iJakQpQtPm8efv"
Note the space between H and i.
How can I stop it from replacing the "+" with a space? I'd really appreciate if someone can give an explanation also.
Btw, I tried (.+?) and (.\++?) and even ([.|\+]+?) - didn't work :(
Thanks,
--Ishtiaque
Updating with screenshots below:
Adding screenshots:
POST Response data:
After parsing with regular expression extractor in JMeter:
Side by side in Notepad++:
'Raw' tab shows the '+'s:
'HTTP' tab does not:
As you get the response in JSON format, I would go with JSON Path Extractor.
It seems to be a much easier approach than using Regular expression.
Below JSON Path should take care of getting the encoded string from your JSON & You should be able to access using ${bigH}.
Check this for more details (scroll down for JSON Path extractor details).
EDIT:
I was wrong that You get the response in JSON format. Are you trying to access - bigH:"XXX" - from script tag? For this, We have to use Regular expression extractor only or Beanshell.
<script type='text/javascript' charset='utf-8'>
registerSubmit(document.forms[0].elements['SubmitTopButton']);
registerSubmit(document.forms[0].elements['SubmitBottomButton']);
(function($) {
$(".wb_tsauthall").wb_tsauthall({
auth : "Authorize All",
unauth : "Unauthorize All",
locMsgKeys : []
});
$(".wb_newedit").wb_newedit({
labels:['Job','Code','Work Premium','Flat Rate','Premium','Shift','Sched Times','LTA','Sched Times w Breaks','Delete Details','Employee Holiday','Work Detail','Schedule Detail'],values:[105,103,200,206,204,450,401,500,461,199,900,100,460],bigH:"PVxUbYIODBT31j8IZnPGxF/9O1iuKAkFzTO9WhXu8An8hAUa22tLiWrEHz8v9SIu/NXZH1a5IxO0xYeNwRIYM+3n1kNsrESnhiAYhwhCiqUY9mI4hvEPgAOx7B+MEB8iSIUyNGNZbeGx9nSogFYpNrzmCXirW7Nm9Tn7owPKHmc8dOf5SZ+eDzAOHIB8+5YzQ3bIdFoe60hOMkyd7FiUXtwPcNMUFEjOSMs9JhgIHTE4agpCdbFb6SLuSuLoO9rqxj+9GovUbzTmrxj4faBKZVATNN7iIFyDZHYAZuZRcPJBdUJ1xNHMCWyPZ4p2/Yk0Q0ujdKJbJw9NFysikZgBFNEhNXEA4w8HL1ycYCmZDgSUW1GsumDAKh0Brq3K8Kh2akep8YEjDMWipKgSPaNx3CVY4lf87e0oK70nK/zKGkmpWFvyMnxbkJtWmeuxmPgRZgg2lYbZXFauD1AidnQQhPULJTTV+P+Xkk9PYm3ZkIEcDnYJUmPg/D3iuwg84m2IZatFTdjiNuDAcGNKptTd54yMgohN87c3sRMiZlSY/r88u+Le3BKWJqyl7Xai7Odqz366DFgOzdPi92LnSaggKX++hy+Z04kjyfSZOUYWmiWlc38SUdeTq2v15egig2mMkSLMaUnHagk="
});
$("#codeSummaryBar").wb_expandableframe({
iframe : contextPath + '/dailytimesheet/summaryInline.jsp'
});
$("#codeSummaryBar").click(function(){$("#codeSummaryBar_expand_collapse_icon").toggleClass("collapse expand");});
$("#codeSummaryBar").click();
$("#selectionBar").wb_expandableframe({
iframe : contextPath + '/dailytimesheet/dailySelectInline.jsp',
onExpand : function() {
$(".selectionBarControl").css("visibility", "hidden");
$("#expand_collapse_icon").removeClass("expand").addClass("collapse");
},
onCollapse : function() {
$(".selectionBarControl").css("visibility", "");
$("#expand_collapse_icon").removeClass("collapse").addClass("expand");
}
});
DTS.onload();
})(jQuery);
</script>
EDIT 2:
I doubt that you might have checked the Encode in the HTTP Request.
Uncheck
Try with the regular expression ([a-zA-Z0-9+]+)
I'm using the regex in Jmeter 2.8 to extract some values from JSON responses.
The response is like that:
{
"key": "prod",
"id": "p2301d",
"objects": [{
"id": "102955",
"key": "member",
...
}],
"features":"product_features"
}
I'm trying to get everything except the text between [{....}] with one regex.
I've tried this one "key":([^\[\{.*\}\],].+?) but I'm always getting the other values between [{...}] (in this example: member)
Do you have any clue?
Thanks.
Suppose you can try to use custom JSON utils for jmeter (JSON Path Assertion, JSON Path Extractor, JSON Formatter) - JSON Path Extractor in this case.
Add ATLANTBH jmeter-components to jmeter: https://github.com/ATLANTBH/jmeter-components#installation-instructions.
Add JSON Path Extractor (from Post Processors components list) as child to the sampler which returns json response you want to process:
(I've used Dummy Sampler to emulate your response, you will have your original sampler)
Add as many extractors as values your want to extract (3 in this case: "key", "id", "features").
Configure each extractor: define variable name to store extracted value and JSONPath query to extract corresponding value:
for "key": $.key
for "id": $.id
for "features": $.features
Further in script your can refer extracted values using jmeter variables (variable name pointed in JSON Path Extractor settings in "Name" field): e.g. ${jsonKey}, ${jsonID}, ${$.features}.
Perhaps it may be not the most optimal way but it works.
My solution for my problem was to turn the JSON into an object so that i can extract just the value that i want, and not the values in the {...}.
Here you can see my code:
var JSON={"itemType":"prod","id":"p2301d","version":"10","tags":[{"itemType":"member","id":"p2301e"},{"itemType":"other","id":"prod10450"}],"multiPrice":null,"prices":null};
//Transformation into an object:
obj = eval(JSON );
//write in the Jmeter variable "itemtype", the content of obj.itemType:prod
vars.put("itemtype", obj.itemType);
For more information: http://www.havecomputerwillcode.com/blog/?p=500.
A general solution: DEMO
Regex: (\[{\n\s*(?:\s*"\w+"\s*:\s*[^,]+,)+\n\s*}\])
Explanation, you don't consume the spaces that you must correctly, before each line there are spaces and you must consume them before matching, that's why isn't your regex really working. You don't need to scape the { char.
I'm testing a web service that returns JSON responses and I'd like to pull multiple values from the response. A typical response would contain multiple values in a list. For example:
{
"name":"#favorites",
"description":"Collection of my favorite places",
"list_id":4894636,
}
A response would contain many sections like the above example.
What I'd like to do in Jmeter is go through the JSON response and pull each section outlined above in a manner that I can tie the returned name and description as one entry to iterate over.
What I've been able to do thus far is return the name value with regular expression extractor ("name":"(.+?)") using the template $1$. I'd like to pull both name and description but can't seem to get it to work. I've tried using a regex "name":"(.+?)","description":"(.+?)" with a template of $1$$2$ without any success.
Does anyone know how I might pull multiple values using regex in this example?
You can just add (?s) to the regex to avoid line breaks.
E.g: (?s)"name":"(.+?)","description":"(.+?)"
It works for me on assertions.
It may be worth to use BeanShell scripting to process JSON response.
So if you need to get ALL the "name/description" pairs from response (for each section) you can do the following:
1. extract all the "name/description" pairs from response in loop;
2. save extracted pairs in csv-file in handy format;
3. read saved pairs from csv-file later in code - using CSV Data Set Config in loop, e.g.
JSON response processing can be implemented using BeanShell scripting (~ java) + any json-processing library (e.g. json-rpc-1.0):
- either in BeanShell Sampler or in BeanShell PostProcessor;
- all the required beanshell libs are currently provided in default
jmeter delivery;
- to use json-processing library place jar into JMETER_HOME/lib folder.
Schematically it will look like:
in case of BeanShell PostProcessor:
Thread Group
. . .
YOUR HTTP Request
BeanShell PostProcessor // added as child
. . .
in case of BeanShell Sampler:
Thread Group
. . .
YOUR HTTP Request
BeanShell Sampler // added separate sampler - after your
. . .
In this case there is no difference which one use.
You can either put the code itself into the sampler body ("Script" field) or store in external file, as shown below.
Sampler code:
import java.io.*;
import java.util.*;
import org.json.*;
import org.apache.jmeter.samplers.SampleResult;
ArrayList nodeRefs = new ArrayList();
ArrayList fileNames = new ArrayList();
String extractedList = "extracted.csv";
StringBuilder contents = new StringBuilder();
try
{
if (ctx.getPreviousResult().getResponseDataAsString().equals("")) {
Failure = true;
FailureMessage = "ERROR: Response is EMPTY.";
throw new Exception("ERROR: Response is EMPTY.");
} else {
if ((ResponseCode != null) && (ResponseCode.equals("200") == true)) {
SampleResult result = ctx.getPreviousResult();
JSONObject response = new JSONObject(result.getResponseDataAsString());
FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir") + File.separator + extractedList);
if (response.has("items")) {
JSONArray items = response.getJSONArray("items");
if (items.length() != 0) {
for (int i = 0; i < items.length(); i++) {
String name = items.getJSONObject(i).getString("name");
String description = items.getJSONObject(i).getString("description");
int list_id = items.getJSONObject(i).getInt("list_id");
if (i != 0) {
contents.append("\n");
}
contents.append(name).append(",").append(description).append(",").append(list_id);
System.out.println("\t " + name + "\t\t" + description + "\t\t" + list_id);
}
}
}
byte [] buffer = contents.toString().getBytes();
fos.write(buffer);
fos.close();
} else {
Failure = true;
FailureMessage = "Failed to extract from JSON response.";
}
}
}
catch (Exception ex) {
IsSuccess = false;
log.error(ex.getMessage());
System.err.println(ex.getMessage());
}
catch (Throwable thex) {
System.err.println(thex.getMessage());
}
As well a set of links on this:
JSON in JMeter
Processing JSON Responses with JMeter and the BSF Post Processor
Upd. on 08.2017:
At the moment JMeter has set of built-in components (merged from 3rd party projects) to handle JSON without scripting:
JSON Path Extractor (contributed from ATLANTBH jmeter-components project);
JSON Extractor (contributed from UBIK Load Pack since JMeter 3.0) - see answer below.
I am assuming that JMeter uses Java-based regular expressions... This could mean no named capturing groups. Apparently, Java7 now supports them, but that doesn't necessarily mean JMeter would. For JSON that looks like this:
{
"name":"#favorites",
"description":"Collection of my favorite places",
"list_id":4894636,
}
{
"name":"#AnotherThing",
"description":"Something to fill space",
"list_id":0048265,
}
{
"name":"#SomethingElse",
"description":"Something else as an example",
"list_id":9283641,
}
...this expression:
\{\s*"name":"((?:\\"|[^"])*)",\s*"description":"((?:\\"|[^"])*)",(?:\\}|[^}])*}
...should match 3 times, capturing the "name" value into the first capturing group, and the "description" into the second capturing group, similar to the following:
1 2
--------------- ---------------------------------------
#favorites Collection of my favorite places
#AnotherThing Something to fill space
#SomethingElse Something else as an example
Importantly, this expression supports quote escaping in the value portion (and really even in the identifier name portion as well, so that the Javascript string I said, "What is your name?"! will be stored in JSON as AND parsed correctly as I said, \"What is your name?\"!
Using Ubik Load Pack plugin for JMeter which has been donated to JMeter core and is since version 3.0 available as JSON Extractor you can do it this way with following Test Plan:
namesExtractor_ULP_JSON_PostProcessor config:
descriptionExtractor_ULP_JSON_PostProcessor config:
Loop Controller to loop over results:
Counter config:
Debug Sampler showing how to use name and description in one iteration:
And here is what you get for the following JSON:
[{ "name":"#favorites", "description":"Collection of my favorite places", "list_id": 4894636 }, { "name":"#AnotherThing", "description":"Something to fill space", "list_id": 48265 }, { "name":"#SomethingElse", "description":"Something else as an example", "list_id":9283641 }]
Compared to Beanshell solution:
It is more "standard approach"
It performs much better than Beanshell code
It is more readable