Parsing a complex JSON object

I need to make the behavior of certain parts of my simulation dependent on the data returned by a call to a RESTful service. The JSON that comes back is relatively complicated:

{result:[<resultset>|<record>,<resultset>|<record>,<resultset>|<record>,<resultset>|<record>,<resultset>|<record>,<resultset>|<record>]}

a resultset is an object that looks like:

{ referenceName: "some-string", limit: 20, offset: 0, total: <n>, recommendations: [<record>,...] }

a record contains information about what was searched for, and depending on which position in the result list, it will have different fields. In one case, it looks like:

`
{
id: #####,
firstName: “first”,
lastName: “last”,
name: “last, first, title”,
location: ,
refs: [,…]
}

`

In the rest, it is missing a few fields, but it is still not a simple object

What I need is to add logic to my scenario that lets it understand what was returned. If a record was returned, some options are available to me. If a resultset, then I have different options. When a resultset, I need to parse the list of results, and be able to pick one, and then transform that data into the format needed for posting back to the server.

In an ideal world, I would be able to parse the whole JSON object, and store it in session as an object, not a string. Then I could navigate it easily enough. But I have not seen anything in the documentation indicating that it is possible to do that. I have seen examples for parsing a single flat object, but not an object with an embedded array of objects in one field that happens to have some number of objects in which you will find other embedded arrays and objects!

What is the shortest path between where I am and what I want to accomplish?

  1. use jsonPath checks and set ofType to Seq or Map, depending on what you expect (array or object)

  2. write doIf conditions as Scala functions, so you can implement whatever complex logic you have

If only my use case were that simple. :frowning:

What I can probably do is just store each of the six elements in the result array and store them as strings in the session. Then, when I need to access them, I can parse them.

In pseudo-code, what I need to do is this:

`
val buildTheRequestBody : Expression[String] = (session: Session) => {
val json = session( ).as[String]
val parsed = JSON_library.parse( json )
if ( parsed.has(“someField”) ) {
// build the string one way, pulling out data from the parsed object
} else {
// build the string a different way, pulling out from different paths
}
}

http( desc ).put( url ).body( StringBody( buildTheRequestBody ) )

`

Can you (someone) send me a link to the documentation, or maybe some sample code, that can show me:

  • How to parse the JSON string once into a data structure that can be searched multiple times
  • How to test if the resulting object has a value at some path
  • How to extract the value at that path

If I can get that much, I should be able to make it do what I want to do. :slight_smile:

Thanks for the help

You can have a look here: https://github.com/gatling/gatling/blob/master/gatling-core/src/test/scala/io/gatling/core/check/extractor/jsonpath/JsonPathExtractorSpec.scala

  1. parse your body string into an AST
  2. use JsonPath expression to get some fields deep into your AST

PS: If you store full response body in the Sessions, don’t forget to clean up once you’re done (remove the attribute), otherwise you’ll leak memory…

elaborate on that, if you will…

Well, if you start storing huge piles of data in the Sessions, and that this Sessions live long enough, old heap usage will increase and result in full GC.
Let’s say you store 100kb of JSON per Session and have 5.000 concurrent virtual users (= alive at the same time), you then have 500Mb of JSON stored in your old heap.

If you store huge documents in the Session, I advice you remove them once you’ve finished using them instead of letting them linger in memory:
exec(session => session.remove(“foo”))

If I am storing the full JSON response, but I always store it in the same session variable, therefore "overwriting" the old one (in an immutable data structure, and all that goes along with it), am I not accomplishing the same thing as I would be if I were deleting it? Thus, there is only one per user? Or does removing the value do somethng special that just replacing it on the next iteration does not do?

If you overwrite the same attribute, yes, you’re fine.