jsonPath stripping quotes

2,076 views
Skip to first unread message

Stella Clemens

unread,
Aug 7, 2014, 2:14:33 PM8/7/14
to gat...@googlegroups.com
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

Nicolas Rémond

unread,
Aug 7, 2014, 2:23:18 PM8/7/14
to gat...@googlegroups.com
Hi,

scala> println(Map("foo"->"bar"))
Map(foo -> bar)

It's just the way it's printed. 

cheers
Nicolas


--
You received this message because you are subscribed to the Google Groups "Gatling User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gatling+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Stella Clemens

unread,
Aug 7, 2014, 2:35:39 PM8/7/14
to gat...@googlegroups.com
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...

Pierre DAL-PRA

unread,
Aug 7, 2014, 4:39:15 PM8/7/14
to gat...@googlegroups.com
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

Stella Clemens

unread,
Aug 7, 2014, 4:53:38 PM8/7/14
to gat...@googlegroups.com
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.

Pierre DAL-PRA

unread,
Aug 7, 2014, 7:02:29 PM8/7/14
to gat...@googlegroups.com
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.

Stella Clemens

unread,
Aug 7, 2014, 7:44:42 PM8/7/14
to gat...@googlegroups.com
Great, thanks!

Pierre DAL-PRA

unread,
Aug 8, 2014, 6:09:32 AM8/8/14
to gat...@googlegroups.com
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

Stella Clemens

unread,
Aug 8, 2014, 1:09:17 PM8/8/14
to gat...@googlegroups.com
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

Pierre DAL-PRA

unread,
Aug 8, 2014, 3:12:36 PM8/8/14
to gat...@googlegroups.com
You're welcome :)
I hope to get this built-in into the RC3 (or final, should the RC2 go smoothly).

Have fun with Gatling !

Cheers,

Pierre

François Laroche

unread,
Aug 11, 2014, 9:23:35 AM8/11/14
to gat...@googlegroups.com
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

Pierre DAL-PRA

unread,
Aug 11, 2014, 9:53:18 AM8/11/14
to gat...@googlegroups.com
@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 ;-)

Cheers, 

Pierre

Stella Clemens

unread,
Aug 11, 2014, 12:22:19 PM8/11/14
to gat...@googlegroups.com
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
Reply all
Reply to author
Forward
Message has been deleted
0 new messages