jsonPath: extract key where value is true

8,053 views
Skip to first unread message

Stig Brautaset

unread,
May 3, 2013, 1:18:50 PM5/3/13
to gat...@googlegroups.com
I have some JSON like this:

{
  "data": {
    "352670": {
      "humdrum": true
    },
    "331230": {
      "humdrum": false
    }
}


I want to extract all the keys under "data" where the value of "humdrum" is true, so in this case I would end up with List(352670). This is what I've tried:

.check(jsonPath("/data/(*)/?(humdrum=true)").findAll.saveAs("humdrums")))

However I'm getting this error Caused by: class org.jaxen.saxpath.XPathSyntaxException: /data/(*)/?(humdrum=true): 6: Expected one of '.', '..', '@', '*', <QName>

It doesn't appear that your jsonPath function matches the expectations I have when reading this:

Is there a way to achieve what I'm after?

Stig

Nicolas Rémond

unread,
May 3, 2013, 1:28:52 PM5/3/13
to gat...@googlegroups.com
Humm ... we are just did a breaking change in that part.

* 1.4.X and 2.0-M1 use a XPath like syntax over Json based on Jackson+Jaxen
* 1.5.0-SNAPSHOT and 2.0-SNAPSHOT are now using the librairy you point out (ie : https://code.google.com/p/json-path/)

As you have a Jaxen error, I guess that you're using 2.0-M1 ?

Here is a 2.0-SNAPSHOT build that will allow to use the more "common" json-path : https://docs.google.com/file/d/0B1zTVlhQrNiyUFhBZzBacGVNZnc/edit









Stig

--
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/groups/opt_out.
 
 

Stéphane Landelle

unread,
May 3, 2013, 2:13:46 PM5/3/13
to gat...@googlegroups.com
Just so that you know: we plan on releasing 1.5.0 and 2.0.0-M2 on monday.

Go there for the exact syntax: http://goessner.net/articles/JsonPath/


2013/5/3 Nicolas Rémond <nicolas...@gmail.com>

Stéphane Landelle

unread,
May 3, 2013, 2:14:34 PM5/3/13
to gat...@googlegroups.com

Stig Brautaset

unread,
May 3, 2013, 6:50:04 PM5/3/13
to gat...@googlegroups.com
Thanks. I can see how to extract the leaves - is it possible to extract the value of the wildcard (*) in this expression?

$.data.*.?(@==true)

Or do I have to resort to parse JSON with regex? It'll be dirty, but with this simple JSON I'm sure it can be done...

Stig

Stéphane Landelle

unread,
May 4, 2013, 5:53:12 AM5/4/13
to gat...@googlegroups.com
Provide a JSON sample and what you're trying to extract and we can show you the proper syntax.


2013/5/4 Stig Brautaset <sbrau...@gmail.com>

Stig Brautaset

unread,
May 4, 2013, 4:07:42 PM5/4/13
to gat...@googlegroups.com
The JSON I have looks like this (it is simplified, of course):

{
  "data": {
    "key-a": {
      "foo": true
    },
    "key-b": {
      "foo": false
    },
    "key-c": {
      "foo": true
    }    
}

I want to extract all the "key-*" where the value of "foo" is true. So from that I expect to end up with: 

List("key-a", "key-c")

I tried a lot of things using the JSONPath expression tester, but I wasn't able to bend it to my will. I then tried to use a transform, before giving up and using a regex. It's dirty, but it works:

      .check(regex(""""(\w+)"\s*:\s*\{\s*"foo"\s*:\s*true""")
        .findAll.transform(x => x.map(_.toSet)).whatever.saveAs("foos")))


Stig

Stéphane Landelle

unread,
May 4, 2013, 4:50:52 PM5/4/13
to gat...@googlegroups.com
Sadly, what you're trying to do will never work because you're trying to gather data from multiple paths. JsonPath, just like XPath, can't do that.
You would need data to be an array of keys that have a name and a foo.

Regex is a solution.
Another one would be to use a bodyString check, and add a transform step  where you would parse it into a JSON AST and extract the values you want.

The JSON engine that's shipped (actually, will be starting next release) with Gatling is json-smart.

Cheers,

Stéphane


2013/5/4 Stig Brautaset <sbrau...@gmail.com>

Stig Brautaset

unread,
May 4, 2013, 6:29:54 PM5/4/13
to gat...@googlegroups.com
Thank you very much again. I like the bodyString approach better than my regex. It works like a charm (I use spray.json since I'm already familiar with it):

  .check(bodyString.transform(x => x.map(y => {
    val json = y.asJson.convertTo[Map[String, Map[String, Map[String, Boolean]]]]
    json("data").filter(_._2("foo")).keySet
  })).whatever.saveAs("foos")))

Stig

Stéphane Landelle

unread,
May 5, 2013, 5:39:15 PM5/5/13
to gat...@googlegroups.com
Nice.

FYI, with json-smart, you would get something like this:

.check(bodyString.transform(_.map(string => {

    val json = parser.parse(is).asInstanceOf[JSONObject]

    json.get("data").asInstanceOf[JSONObject].collect {

        case (key, keyValue: JSONObject) if keyValue.get("foo") == true => key

  }

  })).saveAs("foos")))


2013/5/5 Stig Brautaset <sbrau...@gmail.com>
Reply all
Reply to author
Forward
0 new messages