Gatling JSON Feeder Unique POST Bodies - json

I have a JSON file that contains a JSON Array
test.json
[
{ "Name": "Bob" },
{ "Age": "37" },
{ "DOB": "12/01/1985"}
]
I would like to test each respective element in the JSON array against an endpoint to observe the performance of the system against unique payloads
currently I have
testService.scala
val payload = jsonFile("test.json").circular
val httpProtocol = http
.baseURL("http://test.com")
.headers(Map("Content-Type" -> "application/json"))
val scn = scenario("Test Service")
.feed(payload)
.exec(http("test_request")
.post("/v1/test")
.queryParam("key", "123")
.body()
I am not able to pass each respective child from the payload in the .body() as a JSON
The Gatling Docs say that the JSON Feeder loads the each element of the Array into a record collection
https://gatling.io/docs/2.3/session/feeder/
i.e:
record1: Map("id" -> 19434, "foo" -> 1)
record2: Map("id" -> 19435, "foo" -> 2)
and set the body to .body(StringBody("""[{"id": ${id}}]"""))
The issue is I have different keys (Name,Age,DOB) and I'd like each one to be a different request sent.
.body(StringBody("""[{"KEY_NAME_HERE": ${KEY_NAME_HERE}}]"""))
How do I achieve this?

This is how i am doing:-
company_users.json.json
[
{
"env":"dev",
"userName": "a#test.com",
"password": "Qwerty!12345678"
},
{
"env":"sit",
"userName": "b#test.com",
"password": "Qwerty!12345678"
},
{
"env":"uat",
"userName": "c#test.com",
"password": "Qwerty!12345678"
},
{
"env":"prod",
"userName": "d#test.com",
"password": "Qwerty!12345678"
}
]
Working Code Snippet:
val jsonFileFeederCompany = jsonFile("data/company_users.json").circular
val get_company_user_token = http("Get Company Tokens")
.post(gwt_token_url)
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.body(StringBody(
"""{
"env": "${env}",
"userName": "${userName}",
"password": "${password}"
}"""
)).asJson
.check(status.is(200))
.check(jsonPath("$.jwtToken").saveAs("jwtToken"))
val getCompanyUsersGwtToken = scenario("Create Company GWT token Scenario")
.feed(GetTokenRequest.jsonFileFeederCompany)
.exec(GetTokenRequest.get_company_user_token).exitHereIfFailed
This will read each array[position] from json and replace the values in request, to fetch security tokens from different env.
Hope this helps.
Regards,
Vikram Pathania

In your case JSONs from that array are loaded one by one, and since each first level key from that JSON will be saved as session attribute then users in your simulation end up with just 1 of 3 attributes depending which JSON was used. This way you can't (or to be precise can't easily) build body string. In that simple case it would be better to have JSONs with same fields, so you can rely on them when building request payload. Fe. you can place payload key and value in separate fields:
[
{
"key":"Name",
"value":"Bob"
},
{
"key":"Age",
"value":"37"
},
{
"key":"DOB",
"value":"12/01/1985"
},
]
This way for each user in simulation you will have two attributes key and value so you will be able to construct payload like:
.body(StringBody("""{"${key}": "${value}"}"""))
Of course this will work only in that simple case you described and with string-only values in JSONs. If your final goal is to make something more complex please provide real-life example.

Related

Comparing Json data. Python 3

I have the following Json file and I need to compare data to see how many times each value repeat itself. The problem is, I have no idea about handling Json. I don't want the answer to my exercise, I want to know how to access the data. Json:
{
"tickets": [
{
"ticket_id": 0,
"timestamp": "2016/05/26 04:47:02",
"file_hash": "c9d4e03c5632416f",
"src_ip": "6.19.128.119",
"dst_ip": "145.231.76.44"
},
{
"ticket_id": 1,
"timestamp": "2017/05/28 16:14:22",
"file_hash": "ce8a056490a3fd3c",
"src_ip": "100.139.125.30",
"dst_ip": "145.231.76.44"
},
{
"ticket_id": 2,
"timestamp": "2015/08/23 03:27:10",
"file_hash": "d17f572496f48a11",
"src_ip": "67.153.41.75",
"dst_ip": "239.168.56.243"
},
{
"ticket_id": 3,
"timestamp": "2016/02/26 14:01:33",
"file_hash": "3b28f2abc966a386",
"src_ip": "6.19.128.119",
"dst_ip": "137.164.166.84"
},
]
}
If this is a string representation of the object, first you need to set a variable and parse the string to have object you can work with.
jsonString = "{...your json string...}"
Then parse the string,
import json
jsonObject = json.loads(jsonString)
To access the data within it's like any other js object. Example :
jsonObject.tickets[0].timestamp
would return "2016/05/26 04:47:02"
tickets is the key within the jsonObject, 0 is the index of the first object in the list of tickets.
You can use the built-in "json" library to parse your file into an object:
import json
f = open('myfile.json','r')
tickets = json.loads(f.read())
This will return a "tickets" object. How you "compare" (or what exactly you compare) is up to you.

Process a list of map to get a value of a key in the map

I have a list of map (parsed from json output of a rest request) like
[[Mobile:9876543210, Name:ABCD], [Mobile:8765432109, Name:EFGH], [Mobile:7654321098, Name:IJKL], [Mobile:6543210987, Name:MNOP]]
Original JSON was like
{
"data": [{
"Name": "ABCD",
"Mobile": "9876543210"
},
{
"Name": "EFGH",
"Mobile": "8765432109"
},
{
"Name": "IJKL",
"Mobile": "7654321098"
},
{
"Name": "MNOP",
"Mobile": "6543210987"
}
]
}
I want to get the mobile value from the name
Tried some things but just not working out.
Trying this in JMETER JSR223 post processor using Groovy.
You should be able to get the Mobile based on Name.
Below code fetches the Mobile 8765432109 when Name is EFGH from the OP's data. Similarly you can change the value of Name to get the right Mibile.
//Pass jsonString value to below parseText method
def json = new groovy.json.JsonSlurper().parseText(jsonString)
def result = json.data.find { it.Name == 'EFGH' }.Mobile
println result
You can quickly try online Demo
Here is an example Groovy code to fetch Name:Mobile pairs from the original JSON response (use the code in the JSR223 PostProcessor)
def json = new groovy.json.JsonSlurper().parse(prev.getResponseData())
json.data.each {entry ->
entry.each {k, v -> log.info("${k}:${v}")}
}
Demo:
References:
Groovy: Parsing and producing JSON
Groovy Is the New Black

Dynamically build json using groovy

I am trying to dynamically build some json based on data I retrieve from a database. Up until the opening '[' is the "root" I guess you could say. The next parts with name and value are dynamic and will be based on the number of results I get from the db. I query the db and then the idea was to iterate through the result adding to the json. Can I use jsonBuilder for the root section and then loop with jsonSlurper to add each additional section? Most of the examples I have seen deal with a root and then a one time "slurp" and then joining the two so wasn't sure if I should try a different method for looping and appending multiple sections.
Any tips would be greatly appreciated. Thanks.
{
"hostname": "$hostname",
"path": "$path",
"extPath": "$extPath",
"appName": "$appName",
"update": {"parameter": [
{
"name": "$name",
"value": "$value"
},
{
"name": "$name",
"value": "$value"
}
]}
}
EDIT: So what I ended up doing was just using StringBuilder to create the initial block and then append the subsequent sections. Maybe not the most graceful way to do it, but it works!
//Create the json string
StringBuilder json = new StringBuilder("""{
"hostname": "$hostname",
"path": "$path",
"extPath": "$extPath",
"appName": "$appName",
"update": {"parameter": ["""
)
//Append
sql.eachRow("""<query>""",
{ params ->
json.append("""{ "name": "params.name", "value": "params.value" },""");
}
)
//Add closing json tags
json.append("""]}}""")
If I got your explanation correctly and if the data is not very big (it can live in memory), I'd build a Map object (which is very easy to work with in groovy) and convert it to JSON afterwards. Something like this:
def data = [
hostname: hostname,
path: path,
extPath: extPath,
appName: appName,
update: [parameter: []]
]
sql.eachRow(sqlStr) { row ->
data.update.parameter << [name: row.name, value: row.value]
}
println JsonOutput.toJson(data)
If you're using Grails and Groovy you can utilize grails.converters.JSON.
First, define a JSON named config:
JSON.createNamedConfig('person') {
it.registerObjectMarshaller(Person) {
Person person ->
def output = [:]
output['name'] = person.name
output['address'] = person.address
output['age'] = person.age
output
}
}
This will result in a statically defined named configuration for the Object type of person. Now, you can simply call:
JSON.use('person') {
Person.findAll() as JSON
}
This will return every person in the database with their name, address and age all in one JSON request. I don't know if you're using grails as well in this situation though, for pure Groovy go with another answer here.

JSON for complex and simple data type

Im developing a WCF service that accepts JSON. My method signature accepts 2 parameters, a complex object and a simple type. For all intents and purposes below, assume "servicecredentials" has 2 properties, "username" and "password". I have valid JSON, but when I use a tool like postman I get the error "Expected to find an attribute with name 'type' and value 'object'. Found value 'array'.'"
How should this JSON be posted to the method?
<OperationContract()>
<WebInvoke(method:="POST")>
Function GetStuff(ByVal creds As servicecredentials, ByVal acctNum As String)
The JSON Im posting
[
{
"UserName": "someUSer",
"Password": "p#ssw0Rd"
},
{
"acctNum": "X12362"
}
]
The [] brackets indicate a JSON Array, the {} brackets indicate a JSON Object. If you encompass the array with the {} brackets it will be an object, which is what it seems to be looking for.
Example:
{
"data": [
{
"UserName": "someUSer",
"Password": "p#ssw0Rd"
},
{
"acctNum": "X12362"
}
]
}
The exact internal structure of the JSON depends on how the method will process the data. The error is simply stating that the JSON is not encompassed by an object.

How to add "data" and "paging" section on JSON marshalling

I know i can customize the JSON response registering JSON marshallers to Domain entities, even i can create profiles with names for different responses.
This is done filling an array that later will be marshalled like:
JSON.registerObjectMarshaller(myDomain) {
def returnArray = [:]
returnArray['id'] = it.id
returnArray['name'] = it.name
returnArray['price'] = it.price
return returnArray
}
What i want is to alter the way it gets marshalled to have two sections like
{
"paging": {
"total": 100
},
"data": [
{
"id": 1,
"description": "description 1",
}
},
...
]
}
I assume i have to implemetn a custom JSON Marshaller but i don't know how to use it for a specific response instead of wide application.
EDIT: I assume i'll need a custom RENDERER apart from the marshaller. Is this one that i don't know how to use for specific response.
What about a simple:
def json = new JSON([ paging: [ total: myArray.totalCount ], data: myArray ])
Your domain objects will be converted with the marshaller you have set up while your paging data will simply be transformed into JSON.