Parsing JSON

Hi all,

I’ve been busting my brain for a while solving the following issue. Hopefully someone can help me.

I am posting a get request to an API which results in the following response body (JSON see below). I want to use this response body and post it to another API (API → JSON → API). The catch is that the data key must be removed from the body, before I can post the actual JSON message.

Example Json (a snippet from the response body from 1st API)

{
"data": [{
“price”: {
“NewPrice”: 1
},
“shipping”: [{
“Newprice”: 2
}]
}]
}

Attempts;

  1. I’ve implemented Jsonpath and seems to be a solution but it wraps the JSON as an array [ … ] and therefore can not use it for posting to the second API.

  2. I’ve tried transformResponse and use stripPrefix and stripSuffix to remove the data key. But ran into the issue that I the response is a string not a bytearray.

  3. I’ve tried to use a regex (can’t get it to work). Any ideas on that?

Code snippet of one of the million attempts :slight_smile:

package my.gatling

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._

class OfferApiSimulationTest extends Simulation {

val csvFile = “urls.csv” // CSV input file
val secondApiUrl = “2nd.api.url” //
val run = true

val userUrls = csv(csvFile).circular // queue, shuffle, random, circular

val scn = scenario(“Running OfferApiSimulation”).doIf(run == true) // .repeat(10) // repeat the Simulation a number of times
{
during(60 seconds) {
feed(userUrls)
.exec(
http(“Search”)
.get("${url}")
.check(jsonPath("$.data[*]").findAll.saveAs(“body”))

// .transformResponse {
// case response if response.isReceived =>
// println("*** creating ResponseWrapper")
// new ResponseWrapper(response) {
// val replace : String = response.body.string.stripPrefix("{“data”:[").stripSuffix("]}")

//
// override var replace = response.body.string.stripPrefix("{“data”:[").stripSuffix("]}")

// }
//}.check(regex(".*").findAll saveAs(“newBody”))

).exec(
http(“Next API call”)
.post(secondApiUrl)
.header(“Accept”, “application/json”)
.header(“Content-Type”, “application/json”)
.body(StringBody("${body}")).asJSON
//.body(StringBody("${newBody}")).asJSON

)

}
}

setUp(scn.inject(rampUsers(10) over (60 seconds)))
}

Sorry forgot the version: gatling-charts-highcharts-bundle-2.2.3

Hi Rajan,
if you need

compositeByteData={"price":{"NewPrice":1},"shipping":[{"Newprice":2}]}

in your Next API call it is easy:
use

.check(jsonPath("$..data[*]").saveAs("body"))

instead of

.check(jsonPath("$.data[*]").findAll.saveAs("body"))

Hi,

Thanks a lot for your help, it works like a charm!

For anyone who wants to achieve the same, check below for a complete example. This example code uses a feed(er) to loop through a csv file, then issues a GET request for each line in the CSV.
The response body (in my case JSON) is stored (using jsonPath and saveAs) temporarily and is used as input for a subsequent POST request call to another url. Have fun!

Snippet from startSimulation.sh

#/bin/sh
export GATLING_HOME=/opt/gatling-charts-highcharts-bundle-2.2.3
cd /opt/gatling-charts-highcharts-bundle-2.2.3/bin
./gatling.sh -s my.gatling.ApiSimulation -sf /opt/gatling-charts-highcharts-bundle-2.2.3/user-files/simulations/ApiSimulation -df /opt/gatling-charts-highcharts-bundle-2.2.3/user-files/simulations/ApiSimulation

Snippet from myapi.csv

url
http://first.api.com/v2/1234567
http://first.api.com/v2/1234568
http://first.api.com/v2/1234569

Snippet from ApiSimulation.scala

package my.gatling

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.http.response._
import scala.concurrent.duration._

class ApiSimulation extends Simulation {

val csvFile = “myapi.csv” // CSV input file
val SecondApiUrl = “http://your.api.com/v2/
//val duration = java.lang.Long.getLong(“duration”, 0L) // Duration of run // Getting params from Jenkins
//val rampNUsers = Integer.getInteger(“rampNUsers”, 1) // Total number of users // Getting params from Jenkins
//val rampDuration = java.lang.Long.getLong(“rampDuration”, 0L) // Total duration when all users are connected // Getting params from Jenkins
val run = true

val SecondApiHeaders = Map(
“Accept” → “application/json”,
“Content-Type” → “application/json”)

val userUrls = csv(csvFile).circular // queue, shuffle, random, circular

val scn = scenario(“Running ApiSimulation”).doIf(run == true) // .repeat(10) // repeat the Simulation a number of times
{
during(10 seconds) {
//during(duration seconds) {
feed(userUrls)
.exec(
http(“Call First API Url, from CSV”)
.get("${url}") //
.check(jsonPath("$…data[*]").saveAs(“body”)))
.exec(
http(“Call Second API Url with body from previous call”)
.post(SecondApiUrl)
.headers(SecondApiHeaders)
.body(StringBody("${body}")))

}

}

setUp(scn.inject(rampUsers(10) over (5 seconds)))
//setUp(scn.inject(rampUsers(rampNUsers) over (rampDuration seconds)))
}