Is there a more elegant way to parse this JSON to populate a feeder?

Hello,

I am using the standard library:

`

import scala.util.parsing.json.JSON

`

to parse a chunk of JSON that looks like:

`

{“results”:[
{“columns”:[“id”],
“data”:[{“row”:[“one”],“meta”:[null]},{“row”:[“two”],“meta”:[null]}]}
],
“errors”:[]
}

`

I have an “Initialization” scenario that pulls data from the database and adds it to a csv file which gets used as a feeder by other tests.
It looked like this;

`

val scn = scenario(“Fetch Items”)
.repeat(1) {
exec {
http(“fetch Items”)
.post("/db/data/transaction/commit")
.basicAuth(“neo4j”, “my password”)
.body(StringBody(cypherQuery))
.asJSON
.check(status.is(200))
.check(validatorCheckBuilder2Check(bodyString.transform(body => {

val json:Option[Any] = JSON.parseFull(body)
val map:Map[String,Any] = json.get.asInstanceOf[Map[String, Any]]
val results:List[Any] = map(“results”).asInstanceOf[List[Any]]
val data:Option[List[Map[String, List[String]]]] = results.head.asInstanceOf[Map[String,List[Map[String, List[String]]]]].tail.get(“data”)

if(data.nonEmpty) {
data.head.foreach(d => itemsWriter.println {
d.get(“row”).head.head
})
}

})).exists)
}
}

`

I can sort-of short cut the check to:

`

.check(bodyString.transform(body => {

  val  data:Option[List[Map[String, List[String]]]]  = JSON.parseFull(body) match {
    case Some(m: Map[String, List[Map[String,List[Map[String, List[String]]]]]]) => m("results").head.get("data")
  }

  if (data.nonEmpty) {
    data.head.foreach(d => itemsWriter.println {
      d.get("row").head.head
    })
  }

}).exists)

`

but that still looks pretty ugly. Do you know a more elegant way to do this?

Thanks,
Max

Hey Max,

Personally, I wouldn’t create a Simulation and dump into a file. I would:

  • use AsyncHttpClient to perform the API request in the before {} block of the simulation
  • use Boon or Jackson to parse the response body and then filter the data I want, maybe with a help of our JsonPath library.

Regarding the JSON traversal, you only have 3 choices:

  • cast globally (your second solution) but that just crossing fingers, because of Java (and so Scala) generic type erasure (you might have notice the Scala compiler warnings, telling you that your cast : Map[String, List[Map[String,List[Map[String, List[String]]]]]] doesn’t give you any guarantee about what will happen at runtime)

  • case step by step as your going down (your first solution)

  • project into your own AST (POJO a la Java or Scala case classes), then convert back to Gatling Feeder
    None of those solutions are very satisfying, pick your poison. JSON is intended for Javascript, a weekly and dynamically typed language.

JsonPath might help you with reducing the manual traversal depth.

Cheers