JSON body for an HTTP request needs to look like:
{
"OrderId":"234",
"SupplierId":"JJ889",
"OrderedProducts": [
{
"ProductId":"123",
"Sku":"ABC123",
"Description":"Thing 1"
},
{
"ProductId":"435",
"Sku":"XYZ987",
"Description":"Thing 2"
}
]
}
And I have a CSV file that looks like:
ProductId,Sku,Description
123,ABC123,Thing 1
435,XYZ987,Thing 2
....
But when I substitute "ProductId":"${ProductId}" (and the other variables for sku and description) in the HTTP Request body data I end up with:
{
"OrderId":"234",
"SupplierId":"JJ889",
"OrderedProducts": [
{
"ProductId":"123",
"Sku":"ABC123",
"Description":"Thing 1"
},
{
"ProductId":"123",
"Sku":"ABC123",
"Description":"Thing 1"
}
]
}
How do I ensure my collection of products is unique (i.e. different CSV line) per request?
If you have always 2 products per request, just organize your CSV this way:
ProductId1,Sku1,Description1,ProductId2,Sku2,Description2
And use the new variable names.
Use combination of __StringFromFile() and __javaScript() functions like:
{
"OrderId":"234",
"SupplierId":"JJ889",
"OrderedProducts": [
{
"ProductId":"${__javaScript("${__StringFromFile(file.csv,,,)}".split("\,")[0],)}",
"Sku":"${__javaScript("${__StringFromFile(file.csv,,,)}".split("\,")[1],)}",
"Description":"${__javaScript("${__StringFromFile(file.csv,,,)}".split("\,")[2],)}"
},
{
"ProductId":"${__javaScript("${__StringFromFile(file.csv,,,)}".split("\,")[0],)}",
"Sku":"${__javaScript("${__StringFromFile(file.csv,,,)}".split("\,")[1],)}",
"Description":"${__javaScript("${__StringFromFile(file.csv,,,)}".split("\,")[2],)}"
}
]
}
__StringFromFile() function reads next line from file.csv each time it's being called
__javaScript() function allows executing arbitrary JavaScript code, in above case split() function to break the line into ProductId, Sku and Description.
See Functions and Variables User Manual chapter and How to Use JMeter Functions posts series for more information on JMeter functions.
Related
I've been wondering for some days what kind of scheme would be more appropriate to use a data list in json in a web application.
I'm developing a REST Web Application, and im using Angular for front end, i should order, filter and print these data list also in xml ...
For you what scheme is better and why?
1) {
"datas": [
{ "first":"","second":""},
{ "first":"","second":""},
{ "first":"","second":""}
]
}
2) {
"datas": [{
"data": { "first":"","second":""},
"data": { "first":"","second":""},
"data": { "first":"","second":""}
}]
}
3) [
{ "first":"","second":""},
{ "first":"","second":""},
{ "first":"","second":""}
]
Thanks so much.
The first and third notations are quite similar because the third notation is included in your first.
So the question is "Should I return my datas as an array or should I return an object with a property that contain the array ?
It will depend on either you want to have more information alongside your datas or not.
For exemple, if your API might return an error, you will want to manage it from the front end.
In case of error, the JSON will looks like this :
{
"datas": null,
"error": "An error occured because of some reasons..."
}
At the opposite, if everything goes well and your API actually return the results, it will looks like this :
{
"datas": [
{ "first":"","second":""},
{ "first":"","second":""},
{ "first":"","second":""}
],
"error": null
}
Then your front end can use the error property to manage errors sent from the API.
var result = getDatas(); // Load datas from the API
if(result.error){
// Handle the error, display a message to the user, ...
} else {
doSomething(result.datas); // Use your datas
}
If you don't need to have extra properties like error then you can stick with the third schema.
The second notation is invalid. The datas array will contain only one object which will have one property named data. In this case data is a property that is defined multiple times so the object in the array will contain only the last occurence:
var result = {
"datas": [{
"data": { "first":"a","second":"b"},
"data": { "first":"c","second":"d"},
"data": { "first":"e","second":"f"}
}]
}
console.log("Content of result.datas[0].data : ")
console.log(result.datas[0].data)
Obviously the first option would be easy to use. Once you will access datas it'll give you an array. Any operation (filter, sort, print) on that array will be easy in comparison to anything else. Everywhere you just need to pass datas not datas.data.
If i use just 1 file it works perfectly, but with more than 1 it fails
This is my request
{
"Arguments":{
"InputArguments":[
{
"Resource":"https://s3url.com",
"Name":"HostDwg1-050A-014"
},
{
"Resource":"https://s3url.com",
"Name":"HostDwg1-050A-015"
}
],
"OutputArguments":[
{
"Name":"Result1-050A-014",
"HttpVerb":"PUT",
"Resource":"https:://s3url.com",
"StorageProvider":"Generic"
},
{
"Name":"Result1-050A-015",
"HttpVerb":"PUT",
"Resource":"https://s3url.com",
"StorageProvider":"Generic"
}
]
},
"ActivityId":"PlotToPDF",
"Id":""
}
This is the error i get
The number of Arguments is bigger than the number of Parameters.
Parameter name: Count
How have to be done the request to convert more than one file, without doing a request for each file? thanks
The PlotToPDF activity declares exactly one input parameter and exactly one output parameter. An activity is like a function in a programming language: you can only provide as many arguments as there are parameters. So...
If you want to have a workitem that has more than one input/output argument then you should define an new custom activity that has more than one input/output parameters.
If you want plot multiple files then you should simply submit multiple workitems.
I am trying to create a JSON using Groovy Json Builder in Jmeter.
Below is the code I created to get the desired JSON :
import groovy.json.JsonBuilder
def json = new JsonBuilder()
json {
"Rule":{
"__type":"AndroidSamsungDeviceRelocationRule",
"RuleId":0,
"Name":"Test",
"DeviceFamily":6,
"Targets":{
"Groups":[
{
"Id":"[{LogicalId="${logicalid1}"}]"
}
],
"Devices":[
]
},
"Priority":0,
"IsEnabled":true,
"StartDate":"/Date(${__time(,)})/",
"EndDate":null,
"Mappings":[
{
"RelocationTarget":{
"Id":"${logicalid2}",
"Name":"${__P(TargetGroups)}",
"Path":"\\'${__P(TargetGroups)}'\\",
"PathVisible":"\\'${__P(TargetGroups)}'\\"
},
"IPRange":[
source Double.parseDouble(vars.get("source"))
destination Double.parseDouble(vars.get("destination"))
]
}
],
"EnrollmentCertificateId":null,
"EnrollmentCertificateName":""
}
}
sampler.addNonEncodedArgument("",json.toPrettyString(),"")
sampler.setPostBodyRaw(true)
CSV data is as follows:
0.0.0.0,255.255.255.255
10.0.0.1,255.0.0.0
The above CSV can have multiple values from 1 to 100 IPs separated by ',' .
The code also needs to be modified as per the number of IPs rows.
The ABove CSV data needs to be there under IPRange tag and Result Should be like:
"Rule":{
"__type":"AndroidSamsungDeviceRelocationRule",
"RuleId":0,
"Name":"Test",
"DeviceFamily":6,
"Targets":{
"Groups":[
{
"Id":"[{LogicalId="${logicalid1}"}]"
}
],
"Devices":[
]
},
"Priority":0,
"IsEnabled":true,
"StartDate":"/Date(${__time(,)})/",
"EndDate":null,
"Mappings":[
{
"RelocationTarget":{
"Id":"${logicalid2}",
"Name":"${__P(TargetGroups)}",
"Path":"\\'${__P(TargetGroups)}'\\",
"PathVisible":"\\'${__P(TargetGroups)}'\\"
},
"IPRange":[
{"From":"0.0.0.0","To":"255.255.255.255"},
{"From":"10.0.0.1","To":"255.0.0.1"},
......
.....
]
}
],
"EnrollmentCertificateId":null,
"EnrollmentCertificateName":""
}
But the issue I am getting is "Bad Request" in jmeter.
I fail to see why do you need to build your request body in Groovy, it can be done purely in HTTP Request "Body Data" tab like:
Check out JMeter Parameterization - The Complete Guide for examples on using external data sources for creating data-driven JMeter tests
If you want us to help you with the setup it would be good to see the desired outcome, i.e. JSON payload you would like to generate and the code you've tried as above samples don't make any sense. Get used to check jmeter.log file - normally it contains enough information to get to the bottom of the JMeter test issue. Also I suggest reading Parsing and producing JSON article and JsonBuilder class documentation.
I have the following json:
{
"content":
[
{
"id":1,
"userId":2,
"storeId":8,
"userFirstName":"Max",
"userLastName":"Mustermann",
"city":"Berlin",
"spendQuantity":100,
"paymentStatus":"UNPAID",
"userBalanceStatus":null,
"rateObject":
{
"identifier":23,
"id":"432",
"rate":"1.9345345",
"symbol":"USD",
"rank":2,
}
},
{
"id":2,
"userId":2,
"storeId":3,
"userFirstName":"Newman",
"userLastName":"Mustermann",
"city":"Berlin",
"spendQuantity":1000,
"paymentStatus":"UNPAID",
"userBalanceStatus":null,
"rateObject":
{
"identifier":3,
"id":"234",
"rate":"1.922222245345",
"symbol":"USD",
"rank":2,
}
},
{
"id":3,
"userId":2,
"storeId":3,
"userFirstName":"Newman",
"userLastName":"Mustermann",
"city":"Munich",
"spendQuantity":3000,
"paymentStatus":"UNPAID",
"userBalanceStatus":null,
"rateObject":
{
"identifier":2332,
"id":"234",
"rate":"3.234234",
"symbol":"USD",
"rank":2,
}
},
{
"id":4,
"userId":2,
"storeId":3,
"userFirstName":"Newman",
"userLastName":"Mustermann",
"city":"Essen",
"spendQuantity":4000,
"paymentStatus":"UNPAID",
"userBalanceStatus":null,
"rateObject":
{
"identifier":234,
"id":"234",
"rate":"333.234234",
"symbol":"USD",
"rank":2,
}
}
}
But I need to verify it partially - Only the fields in the nested jsons where city is Berlin or Essen, but without the rateObject (I don't need to verify this part). With other words I need to verify nested jsons with ids- 1,2,4 - all fields, without the information in rateObject.
Partial Answer and Suggestion:
We can apply the filter condition in the JSON Query to fetch the matched details.
For Example: To get the id of the mentioned city,
JSON Query:
$.content[?(#.city=="Berlin" || #.city=="Essen")].id
Output:
[
1,
2,
4
]
Similarly, you can assert all the required fields using the filter JSON Query.
JMeter JSON Extractor will provide only one value at a time.So, you can either add some logic to verify all the occurrences or multiple verification can be added by specifying the id index ( $.content[?(#.city=="Berlin" || #.city=="Essen")].id[0] --> It gives the first occurrence Id )
If you want to validate multiple fields,then you can write the customized script in Bean Shell Post Processor.(Refer the below link and you will get some idea)
Extracting JSON Response using Bean Shell Postprocessor
If you are using the Bean Shell Post Processor, then required java jar files should be placed in JMeter ClassPath( Folder: apache-jmeter-4.0\lib\ext)
Consider a subset of a sample output from http://demo.nginx.com/status:
{
"timestamp": 1516053885198,
"server_zones": {
"hg.nginx.org": {
... // Data for "hg.nginx.org"
},
"trac.nginx.org": {
... // Data for "trac.nginx.org"
}
}
}
The keys "hg.nginx.org" and "track.nginx.org" are quite arbitrary, and I would like to parse them into something meaningful for Elasticsearch. In other words, each key under "server_zones" should be transformed into a separate event. Logstash should thus emit the following events:
[
{
"timestamp": 1516053885198,
"server_zone": "hg.nginx.org",
... // Data for "hg.nginx.org"
},
{
"timestamp": 1516053885198,
"server_zone": "trac.nginx.org",
... // Data for "trac.nginx.org"
}
]
What is the best way to go about doing this?
You can try using the ruby filter. Get the server zones and create a new object using the key value pairs you want to include. From the top of my head, something like below should work. Obviously you then need to map the object to your field in the index. Change the snipped based on your custom format i.e. build the array or object as you want.
filter {
ruby {
code => " time = event.get('timestamp')
myArr = []
event.to_hash.select {|k,v| ['server_zones'].include?(k)}.each do |key,value|
myCustomObject = {}
#map the key value pairs into myCustomObject
myCustomObject[timestamp] = time
myCustomObject[key] = value
myArr.push(myCustomObject) #you'd probably move this out based on nesting level
end
map['my_indexed_field'] = myArr
"
}
}
In the output section use rubydebug for error debugging
output {
stdout { codec => rubydebug }
}