Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gatling - Looping through JSON array

I have a block of code which needs to loop through a JSON array which is obtained from response of a REST service. (Full gist available here.)

.exec(http("Request_1")
  .post("/endPoint")
  .headers(headers_1)
  .body(StringBody("""REQUEST_BODY""")).asJSON
  .check(jsonPath("$.result").is("SUCCESS"))
  .check(jsonPath("$.data[*]").findAll.saveAs("pList")))
.exec(session => {
  println(session)
  session
})
.foreach("${pList}", "player"){
 exec(session => {
    val playerId = JsonPath.query("$.playerId", "${player}")
    session.set("playerId", playerId)
  })
 .exec(http("Request_1")
    .post("/endPoint")
    .headers(headers_1)
    .body(StringBody("""{"playerId":"${playerId}"}""")).asJSON
    .check(jsonPath("$.result").is("SUCCESS")))

}

The response format of the first request was

{
  "result": "SUCCESS",
  "data": [
    {
      "playerId": 2
    },
    {
      "playerId": 3
    },
    {
      "playerId": 4
    }
  ]
}

And playerId shows up in the session as

pList -> Vector({playerId=2, score=200}, {playerId=3, score=200}

I am seeing in the second request the body is

{"playerId":"Right(empty iterator)}

Expected : 3 requests with body as

 {"playerId":1}
 {"playerId":2}
 {"playerId":3}

I can loop over the resulting array successfully if I save just the playerIds:

.check(jsonPath("$.data[*].playerId").findAll.saveAs("pList")))
like image 229
Neil Avatar asked Aug 13 '14 14:08

Neil


1 Answers

I managed to get the requests you're looking for sent out (although still getting a 404, but that might be server-side or the request your gist is sending might be missing something). The trick was to give up on JsonPath entirely:

.exec(http("Request_10")
  .get("gatling1")
  .headers(headers_10)
  .check(jsonPath("$.result").is("SUCCESS"),
  jsonPath("$.data[*]").ofType[Map[String,Any]].findAll.saveAs("pList")))
.foreach("${pList}", "player") {
  exec(session => {
    val playerMap = session("player").as[Map[String,Any]]
    val playerId = playerMap("playerId")
    session.set("playerId", playerId)
  })

Here, the jsonPath check can automatically store your JSON object as a map, and then you can access the player ID by key. The value type doesn't have to be Any, you could use Int or Long if all your values are numbers. If you want more info on what went wrong with JsonPath, read on.


Your first problem is that JsonPath.query() doesn't just return the value you're looking for. From the JsonPath readme:

JsonPath.query("$.a", jsonSample) gives you Right(non-empty iterator). This will allow you to iterate over all possible solutions to the query.

Now, when it says Right(non-empty iterator), I assumed that meant the iterator was not empty. However, if you try this:

val playerId = JsonPath.query("$.playerId", session("player").as[String]).right.get
println(playerId)

...it prints "empty iterator". I'm not sure whether it's a problem with JsonPath, the jsonPath check, or usage somewhere in between, but there's not quite enough documentation for me to want to dig into it.

like image 148
Michelle Avatar answered Sep 18 '22 15:09

Michelle