Need help in extracting values from Json for Jmeter - json

My Json is like below, I want to extract json for all the "code" values and put them with comma separated. **I have almost 250 code values and want them like this
RFI027,RFI037,RFI407,RFI055,RFI457,RFI677,RFI068,RFI086
{
"totalDocs":202,
"recordBatchSize":224,
"listingType":31,
"currentPageNo":1,
"recordStartFrom":18,
"columnHeader":[
{
"id":"0",
"fieldName":"commId",
"isCustomAttributeColumn":false,
"isActive":false
},
{
"id":"24264704",
"function":"",
"funParams":"",
"wrapData":"",
},
{
"code":"RFI027",
"noOfActions":0,
"observationId":0
},
{
"code":"RFI037",
"noOfActions":0,
"observationId":0
},
{
"code":"RFI407",
"noOfActions":0,
"observationId":0
},
{
"code":"RFI055",
"noOfActions":0,
"observationId":0
},
{
"code":"RFI457",
"noOfActions":0,
"observationId":0
},
{
"code":"RFI677",
"noOfActions":0,
"observationId":0
},
{
"code":"RFI068",
"noOfActions":0,
"observationId":0
},
{
"code":"RFI086",
"noOfActions":0,
"observationId":0
},
],
"sortField":"updated",
"sortFieldType":"timestamp",
"sortOrder":"desc",
"editable":true,
"isIncludeSubFolder":true,
"totalListData":0
}
I tried with $..code in Jmeter Json Extractor but it returns only one Value. but I want output like RFI027,RFI037,RFI407,RFI055,RFI457,RFI677,RFI068,RFI086. As I want to pass all values in another request. I have tried with 0,1,2,3 and -1 match no. but it returns only one value, while for -1 it returns ${ref_formCode1}. Appreciate your help. Thank you in advanced.
Edit:
After implementing JSR223 post-processer It shows blank field. Here are the screenshots.

You can achieve this using a JSR223 post-processer using the following code, meanwhile notice there are few syntactical errors in your JSON,
Add the JSR223 post-processer to your request and this will do your ask
import groovy.json.JsonSlurper;
def response = new groovy.json.JsonSlurper().parse(prev.getResponseData());
def CodeFile = '';
response.columnHeader.code.each {
Code->if (Code == null) {}
else {
CodeFile += Code + ',' //this will have your code but there will be ',' at the last
}
}
def CodeFileList = CodeFile.subSequence(0, CodeFile.length() - 1) // this will remove the last ,
log.info('CodeFile:' + CodeFileList)
vars.put("CodeList",CodeFileList)
If the code value is inside the data
import groovy.json.JsonSlurper;
def response = new groovy.json.JsonSlurper().parse(prev.getResponseData());
def CodeFile = '';
response.data.code.each {Code->
if (Code == null) {}
else {
CodeFile += Code + ',' //this will have your code but there will be ',' at the last
}
}
def CodeFileList = CodeFile.subSequence(0, CodeFile.length() - 1) // this will remove the last ,
log.info('CodeList:' + CodeFileList)
vars.put("CodeList",CodeFileList)
Usage: Inside request body
Inside the request URL
In another controller,
==========
After edit in the main question:

You're almost there, you just need to:
Set "Match No" to -1
Tick Compute concatenation var box
It will give you the ${ref_formCode1_ALL} JMeter Variable holding all codes matched by you JsonPath query separated by commas:
More information: How to Use the JSON Extractor For Testing

Related

Unable to parse JSON data due to errors or undefined data

I apologize if this seems similar to other questions asked but I have not been able to find any posts that have resolved this issue for me. Basically, I am getting a JSON object and I am trying to parse it but I can't parse it correctly. Mainly the WordDetails section that I am getting from a Word API. I am able to get everything outside the results section under WordDetails. Basically, when I get to results, I am not able to parse it correctly. Below is an example of the format.
{
"LastIndex": 133,
"SRDWords": [
{
"Domain": {
"URL": "abactinal.com",
"Available": true
},
"WordDetails": "{\"word\":\"abactinal\",\"results\":[{\"definition\":\"(of radiate animals) located on the surface or end opposite to that on which the mouth is situated\",\"partOfSpeech\":null,\"antonyms\":[\"actinal\"]}],\"syllables\":{\"count\":4,\"list\":[\"ab\",\"ac\",\"ti\",\"nal\"]}}"
},
{
"Domain": {
"URL": "aaronical.com",
"Available": true
},
"WordDetails": "{\"word\":\"aaronical\",\"syllables\":{\"count\":4,\"list\":[\"aa\",\"ron\",\"i\",\"cal\"]},\"pronunciation\":{\"all\":\"ɜ'rɑnɪkəl\"}}"
},
...
Here is my code below. Basically, I am getting to the results section of WordDetails but if I try to parse the results section it fails and if I try object.entries on it, it will not return a response according to the alert messages I used. I know there must be a better way but not sure what. Most articles say just JSON.parse then map it but that does not work. Any help would be appreciated!
data.Words.map(word => {
//get data
for (let [key, value] of Object.entries(word)) {
if (key === "Domain") {
url = value.URL;
availability = value.Available;
} else if (key.trim() === "WordDetails") {
alert("value " + value);
wDetails = JSON.parse(value);
for (let [key2, value2] of Object.entries(wDetails)) {
if (key2 === "word") {
//store word
} else if (key2.toString().trim() === "results") {
let test = JSON.parse(value2);
test = Object.entries(value2);
test.map(t => {
alert(t.definition);
});
}
}
}
}
});
You did JSON.parse above, no need to parse value2 again.
And value for results is an array, so no need for Object.entries.
...
} else if (key2.toString().trim() === 'results') {
let test = JSON.parse(value2); // this should be remove
test = Object.entries(value2); // this should be remove, value2 should be an array
// map value2 directly
value2.map(t => {
alert(t.definition);
});
}
...

Converting JSON data to CSV in Cloudant using List and View

I tried to convert the JSON data in my Cloudant db to csv format, using the List function. It works perfectly for all values except JSON array values, i.e. the nested values. For these, I am getting [object object] as the output in my csv document.
Please find the sample JSON document which I am using, below:
{
"NAME": "Aparna",
"EMAIL": "something#domain.com",
"PUBLIC_OFFICIALS_CONTACTED": [
{ "NAME_PUBLIC_OFFICIAL": [ "ab"],
"TITLE_PUBLIC_OFFICIAL": ["cd"]}
],
"COMMUNICATION_TYPE": [
"Meeting",
"Phone",
"Handout",
"Conference"
],
"NAMES_OF_OTHERS_FROM_IBM": [
{ "NAME_OF_OTHERS": ["ef"],
"TITLE_OF_OTHERS": [ "gh"]}
],
"COMMUNICATION_BENEFIT": "Yes",
"LAST_UPDATE_BY" : "ap"
}
Please find the map and list functions used below :
"map" : "function(doc){
if((\"SAVE_TYPE_SUBMIT\" in doc) && (doc.SAVE_TYPE_SUBMIT== \"Submit\")) {
emit (doc. LAST_UPDATE_BY,[doc.NAME,doc.EMAIL,doc.PUBLIC_OFFICIALS_CONTACTED[0].NAME_PUBLIC_OFFICIAL,\n doc.PUBLIC_OFFICIALS_CONTACTED[0].TITLE_PUBLIC_OFFICIAL,doc.COMMUNICATION_TYPE,doc.NAMES_OF_OTHERS_FROM_IBM[0].NAME_OF_OTHERS, doc.NAMES_OF_OTHERS_FROM_IBM[0].TITLE_OF_OTHERS, doc.COMMUNICATION_BENEFIT,doc. LAST_UPDATE_BY,doc.LAST_UPDATE_DATE]) ;
}
}
"list" : "function (head, req) {
var row;
start({\n headers: {'Content-Type': 'text/csv' },
});
var first = true;
while(row = getRow()) {
var doc = row.doc;
if (first) {
send(Object.keys(doc).join(',') + '\\n');
first = false;\n }
var line = '';
for(var i in doc) {
// comma separator
if (line.length > 0) {
line += ',';\n }
// output the value, ensuring values that themselves
// contain commas are enclosed in double quotes
var val = doc[i];
if (typeof val == 'string' && val.indexOf(',') > -1) {
line += '\"' + val.replace(/\"/g,'\"\"') + '\"';
}
else {
line += val;
}
}
line += '\\n';
send(line);
}}"
Note : In the map, only the first values have been fetched from the JSON arrays for now, on purpose, to simplify the function.
Please help understand how to fetched the nested JSON values or arrays and download the same in csv format. Any guidance would be much appreciated!
You can try to stringify the object you are trying to export and you will get some clue
if (typeof val == 'string' && val.indexOf(',') > -1) {
line += '\"' + val.replace(/\"/g,'\"\"') + '\"';
}
else {
line += JSON.stringify(val);
}
Or even better
if (typeof val == 'string' && val.indexOf(',') > -1) {
line += '\"' + val.replace(/\"/g,'\"\"') + '\"';
}
else if(val instanceof Array){
line += val.join(',');
}
else {
line += JSON.stringify(val);
}
There are a couple of things to change here that might help. The first thing is that you don't need to emit all the values you want to use, because you can access the document itself from the list when dealing with a view.
With this in mind, the map could have an emit like
emit (doc.LAST_UPDATE_BY, null);
With this in place, if you request the list/view with include_docs=true then you can refer to the fields in your document inside the while(row = getRow()) section like this:
send(row.doc.NAME + ',' + row.doc.EMAIL + '\\n');
And for the nested documents, try something like:
row.doc.PUBLIC_OFFICIALS_CONTACTED.0.NAME_PUBLIC_OFFICIAL
You already referred in another question to the article I'd recommend for a full working example https://developer.ibm.com/clouddataservices/2015/09/22/export-cloudant-json-as-csv-rss-or-ical/ - hopefully this explanation helps also.

Angular reading data from json into textarea

I'm trying to read some test data from a local json file and output the data with correct formatting into a textarea. Right now though it just outputs [object Object]. How would I go about getting it so it outputs:
Id: theIdGoesHere
Title: theTitleGoesHere
step.service.ts The service used to call the json data
public getJson(): Observable<any>{
return this.http.get('/assets/jsonData/MyJson.json')
.map(response => response.json());
}
MyJson.json
{
"data":[
{
"id": 1,
"title":"Test1"
},
{
"id": 2,
"title":"Test2"
}
]
}
main.componenet.ts
private testVar: any;
test(){
this.stepService.getJson().subscribe(data => (this.testVar = data));
}
anothermethod(){
this.test();
this.mainStepText = this.testVar; //mainStepText binded to textarea with [(ngModel)]="mainStepText"
}
get mainStepText2() { //Rebinded this one
const text = [];
const { data } = this.testVar;
for (let item of this.testVar.data) {
Object.keys(item).forEach(key => {
text.push(key + ': ' + item[key]);
});
}
return text.join('\r\n'); // \r\n is the line break
}
You can use json pipe to format your object into a json string:
[(ngModel)]="mainStepText | json"
If you want to show a specific property of your object, you can access it in your template:
[(ngModel)]="mainStepText.data[0].title"
This will display "Test1" in your field.
You could loop through your json.data and through their keys to extract the text and values and generate the string you need for the text area.
const text = [];
for (let item of this.textVar.data) {
Object.keys(item).forEach(key => {
text.push(key + ': ' + item[key]);
});
}
return text.join('\r\n'); // \r\n is the line break
Here's the running code, I put it in app.ts: http://plnkr.co/edit/3AbQYQOW0MVBqO91X9qi?p=preview
Hope this is of help.

Creating CSV view from CouchDB

I know this should be easy, but I just can't work out how to do it despite having spent several hours looking at it today. There doesn't appear to be a straightforward example or tutorial online as far as I can tell.
I've got several "tables" of documents in a CouchDB database, with each "table" having a different value in a "schema" field in the document. All documents with the same schema contain an identical set of fields. All I want to do is be able to view the different "tables" in CSV format, and I don't want to have to specify the list of fieldnames in each schema.
The CSV output is going to be consumed by an R script, so I don't want any additional headers in the output if I can avoid them; just the list of fieldnames, comma separated, with the values in CSV format.
For example, two records in the "table1" format might look like:
{
"schema": "table1",
"field1": 17,
"field2": "abc",
...
"fieldN": "abc",
"timestamp": "2012-03-30T18:00:00Z"
}
and
{
"schema": "table1",
"field1": 193,
"field2": "xyz",
...
"fieldN": "ijk",
"timestamp": "2012-03-30T19:01:00Z"
}
My view is pretty simple:
"all": "function(doc) {
if (doc.schema == "table1") {
emit(doc.timestamp, doc)
}
}"
as I want to sort my records in timestamp order.
Presumably the list function will be something like:
"csv": "function(head, req) {
var row;
...
// Something here to iterate through the list of fieldnames and print them
// comma separated
for (row in getRow) {
// Something here to iterate through each row and print the field values
// comma separated
}
}"
but I just can't get my head around the rest of it.
If I want to get CSV output looking like
"timestamp", "field1", "field2", ..., "fieldN"
"2012-03-30T18:00:00Z", 17, "abc", ..., "abc"
"2012-03-30T19:01:00Z", 193, "xyz", ..., "ijk"
what should my CouchDB list function look like?
Thanks in advance
The list function that works with your given map should look something like this:
function(head,req) {
var headers;
start({'headers':{'Content-Type' : 'text/csv; charset=utf-8; header=present'}});
while(r = getRow()) {
if(!headers) {
headers = Object.keys(r.value);
send('"' + headers.join('","') + '"\n');
}
headers.forEach(function(v,i) {
send(String(r.value[v]).replace(/\"/g,'""').replace(/^|$/g,'"'));
(i + 1 < headers.length) ? send(',') : send('\n');
});
}
}
Unlike Ryan's suggestion, the fields to include in the list are not configurable in this function, and any changes in order or included fields would have to be written in. You would also have to rewrite any quoting logic needed.
Here some generic code that Max Ogden has written. While it is in node-couchapp form, you probably can get the idea:
var couchapp = require('couchapp')
, path = require('path')
;
ddoc = { _id:'_design/csvexport' };
ddoc.views = {
headers: {
map: function(doc) {
var keys = [];
for (var key in doc) {
emit(key, 1);
}
},
reduce: "_sum"
}
};
ddoc.lists = {
/**
* Generates a CSV from all the rows in the view.
*
* Takes in a url encoded array of headers as an argument. You can
* generate this by querying /_list/urlencode/headers. Pass it in
* as the headers get parameter, e.g.: ?headers=%5B%22_id%22%2C%22_rev%5D
*
* #author Max Ogden
*/
csv: function(head, req) {
if ('headers' in req.query) {
var headers = JSON.parse(unescape(req.query.headers));
var row, sep = '\n', headerSent = false, startedOutput = false;
start({"headers":{"Content-Type" : "text/csv; charset=utf-8"}});
send('"' + headers.join('","') + '"\n');
while (row = getRow()) {
for (var header in headers) {
if (row.value[headers[header]]) {
if (startedOutput) send(",");
var value = row.value[headers[header]];
if (typeof(value) == "object") value = JSON.stringify(value);
if (typeof(value) == "string") value = value.replace(/\"/g, '""');
send("\"" + value + "\"");
} else {
if (startedOutput) send(",");
}
startedOutput = true;
}
startedOutput = false;
send('\n');
}
} else {
send("You must pass in the urlencoded headers you wish to build the CSV from. Query /_list/urlencode/headers?group=true");
}
}
}
module.exports = ddoc;
Source:
https://github.com/kanso/kanso/issues/336

Bitly, Json, and C#

I'm working on something that involved using the Bit.ly API, and allow the user to select theformat (Text, XML, Json) the text & XML are completed. This is the Json result that is returned when you shorten a URL:
{
"status_code": 200,
"status_txt": "OK",
"data":
{
"long_url": "http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}",
"url": "http:\/\/rlm.cc\/gtYUEd",
"hash": "gtYUEd",
"global_hash": "evz3Za",
"new_hash": 0
}
}
And this C# code works just fine to parse it and get the short URL:
var serializer2 = new JavaScriptSerializer();
var values2 = serializer2.Deserialize<IDictionary<string, object>>(json);
var results2 = values2["data"] as IDictionary<string, object>;
var shortUrl2 = results2["url"];
expandedUrl = results2["url"].ToString();
return results2["url"].ToString();
Now here's the Json sent back when expanding a URL:
{
"status_code": 200,
"status_txt": "OK",
"data":
{
"expand":
[
{
"short_url": "http:\/\/rlm.cc\/gtYUEd",
"long_url": "http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}",
"user_hash": "gtYUEd",
"global_hash": "evz3Za"
}
]
}
}
Ad that's where my problem begins, how can I change my current C# to be able to handle both scenarios, because as you can see their vastly different from each other. Any ideas?
I usually use Json.NET to cherrypick values out of JSON documents. The syntax is very concise. If you reference NewtonSoft.Json.dll and use Newtonsoft.Json.Linq, you can write the following:
var job = JObject.Parse(jsonString);
if (job["data"]["expand"] == null)
{
Console.WriteLine((string)job["data"]["url"]);
}
else
{
Console.WriteLine((string)job["data"]["expand"][0]["long_url"]);
}
If jsonString is:
string jsonString = #"{""status_code"": 200, ""status_txt"": ""OK"", ""data"": {""long_url"": ""http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}"", ""url"": ""http:\/\/rlm.cc\/gtYUEd"", ""hash"": ""gtYUEd"", ""global_hash"": ""evz3Za"", ""new_hash"": 0 }}";
the routine will display http://rlm.cc/gtYUEd.
If jsonString is:
string jsonString = #"{""status_code"": 200, ""status_txt"": ""OK"", ""data"": { ""expand"": [ { ""short_url"": ""http:\/\/rlm.cc\/gtYUEd"", ""long_url"": ""http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}"", ""user_hash"": ""gtYUEd"", ""global_hash"": ""evz3Za"" } ] } }";
the routine will display http://panel.aspnix.com/Default.aspx?pid={Removed}.
Not sure I got your problem. Why aren't you testing, if you got a shortening result or a expanding result? Since they are different, this could easily be done via simple 'if ()' statements:
if (results2.ContainsKey("expand")) {
// handle the expand part
} else {
// handle the shorten part
}
Assuming that the provider is consistent with which form it sends, do you need to have code that handles both? It should be direct to handle each individually.
If you can't know ahead of time which format you will get back, you can do the following:
if (results2.ContainsKey("expand"))
{
//Second example
}
else
{
//First example
}