jsonPath stripping quotes

Hello,

I’m having a bit of trouble with jsonPath. I’m using it to select out and save json objects in the session so that I can later use them in generating a request, but it seems like using jsonPath removes the quotation marks from what it’s saving. I used extraInfoExtractor to pull the response body and this is what it looks lie:

StringResponseBody({"data":[{"label":"Hourly","value":1},{"label":"Salary","value":2}],"notification":null,"status":"success"},UTF-8)

So I use jsonPath on it like this:

.check(jsonPath("$.data[?(@.label == 'Salary')]").saveAs("selectedPaymentType"))

But then when I dump the session I get this:

selectedPaymentType -> {label=Salary, value=2}

All of the quotation marks have been removed and it doesn’t work in the later call (where it is being dropped into a larger json blob). Is there another way to deal with this or am I going to have to use regex?

Thanks,

  • Stella

Hi,

println(Map(“foo”->“bar”))
Map(foo → bar)

It’s just the way it’s printed.

cheers
Nicolas

I thought so to, but then I did this:

`
.exec((s) => {println(s.attributes(“selectedPaymentType”).getClass) ;s})

`

and I got this:

class java.lang.String

So I did this:

.check(jsonPath("$.data[?(@.label == 'Salary')]").ofType[String].saveAs("selectedPaymentType"))

`

.exec((s) => {

println(s.attributes(“selectedPaymentType”).getClass)
println(s.attributes(“selectedPaymentType”))
s
})

`

The results:

`

class java.lang.String
{label=Salary, value=2}

`

I’m pretty sure it’s not nor was it ever (at least in my control) a Map…

Hi Stella,

Gatling doesn’t currently give back an Map if the jsonPath query points to an object.
Gatling 1.5.x behaviour was the same on that regard.
Please note that, as this would be a new feature, it would have to wait until September and Gatling 2’s stable release, and it would target Gatling 2.1.

However, you don’t need to go all the way back to regexes if you want to fetch both the “label” and “value” attributes, you can simply split up your check to search and save each attribute separately :

.check(jsonPath("$.data[?(@.label == ‘Salary’)].label").saveAs(“selectedPaymentLabel”))
.check(jsonPath("$.data[?(@.label == ‘Salary’)].value").saveAs(“selectedPaymentValue”))

Hope this helps !

Cheers,

Pierre

The problem is that this is the simplest of the JSON blobs I have to path out, the other ones are dozens, maybe as much as a hundred elements. Plus, I don’t want the Map, I want the JSON string exactly as it is in the response. My problem isn’t that I was to get at the values and can’t, the problem is that the json it’s returning me is invalid because it’s missing the quotes.

Ok, I finally understand what is the root of the problem here.
What you get out of your jsonPath query is a Java Map but, whether it’s coming from your .ofType[String] or when you’re dumping the session, you always end to see the string representation of a Java Map, which happens to look like JSON without quotes. The fact that they look alike is merely a coincidence.

In fact, what Gatling’s missing in order to achieve what you want to do is a way to take the result of a jsonPath query and turning it back to a JSON String.
I opened an issue to add it right away and it will be included in Gatling 2.0.0-RC2, scheduled (hopefully) for tomorrow.

Great, thanks!

Little update :

As I’m not that familiar with the internal workings of the Checks API, I might need a bit more time to get it right, but we’ll still need to release a RC2 very soon, as it would embark a few critical fixes.
Would you be okay, for the time being, with a “fix” on your side to get your simulation working as you expect, until I can find to way to provide this as a built in ?

Basically, what you need, and what I’m trying to simplify, is this :

`
import io.gatling.json.Jackson.TheObjectMapper
def toJsonString(obj: Any) = TheObjectMapper.writeValueAsString(obj)

jsonPath(…).ofType[Any].transform(obj => toJsonString(obj).saveAs(…)
`

Cheers,

Pierre

Yeah, I was thinking along a similar line. Here’s what I came up with:

def mapToJson = (obj: Any) => io.gatling.core.json.Jackson.TheObjectMapper.writeValueAsString(obj)

.check(jsonPath("$.data[?(@.label == 'Salary')]").ofType[Any].transform(mapToJson).saveAs("selectedPaymentType"))

.exec(s => {println(s.attributes("selectedPaymentType")); s})

and it resulted in this:

`
{“label”:“Salary”,“value”:2}

`

Thanks so much for all your support!

  • Stella

You’re welcome :slight_smile:
I hope to get this built-in into the RC3 (or final, should the RC2 go smoothly).

Have fun with Gatling !

Cheers,

Pierre

Another way that may fit you is using the result as a map, and keeping it a map.

For that, you can declare a JsonFilter like that :

implicit val jMaptoMapFilter = new JsonFilter[mutable.Map[Any, Any]] {
import scala.collection.JavaConversions._
override def filter: PartialFunction[Any, mutable.Map[Any, Any]] = {
case e: java.util.Map[Any, Any] => mapAsScalaMap(e)
}
}

(I’m not a pro on scala generics, so I’m not sure as how to get rid of warnings)

and then you can do :

.check(jsonPath("$.data[?(@.label == ‘Salary’)]").ofType[mutable.Map[Any, Any]] saveAs “selectedPaymentType”)

Hope it can help.

François

@Francois : Note that if don’t require mutable maps, there is already a JsonFilter defined for Map[String, Any] : https://github.com/gatling/gatling/blob/master/gatling-core/src/main/scala/io/gatling/core/check/extractor/jsonpath/JsonFilter.scala#L52 :wink:

Cheers,

Pierre

François -

Thanks for the advice, but I don’t think I can use the data in Map format. I would need to retrieve it and then convert it back into json anyway, so it would result in a slightly more complicated version of what I wrote above anyway.

  • Stella