How to use dynamic JSON Path Expressions with JSON Extractor?

3,039 views
Skip to first unread message

rafael.a...@gmail.com

unread,
Jul 7, 2016, 12:39:36 PM7/7/16
to jmeter-plugins
Hello!

I am trying to filter a JSON based on the value of a child element dynamically.

Below is an example of what I want to achieve:

Sample JSON
{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

Expression:
$..book[?(@.title=${TITLE})]

.. where TITLE would then be a variable that changes from thread to thread.

Is this something that would be possible to do it with JSON Path Extractor? Is there an alternative route?

Thanks a lot in advance!


Tom Tran

unread,
Jul 7, 2016, 12:53:12 PM7/7/16
to jmeter-plugins, rafael.a...@gmail.com
Hi,

This expression can work if you change it to

$..book[?(@.title == '${TITLE}')]

The result likes this:

TITLE=The Lord of the Rings
book=[{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]
book_1={"category":"fiction","title":"The Lord of the Rings","author":"J. R. R. Tolkien","price":22.99,"isbn":"0-395-19395-8"}
book_matchNr=1

For more usage, you can refer:

rafael.a...@gmail.com

unread,
Jul 7, 2016, 4:28:01 PM7/7/16
to jmeter-plugins, rafael.a...@gmail.com
Hello Tom!

Thanks a bunch for the response, it solved my problem!!

I do have a follow up question that I couldn't sort out from the link you suggested, if that is ok.
I am having a lot of trouble with filtering in the parent element with the JSON Extractor..

Sample JSON
{
 
"employees": [
   
{
     
"firstName": "John",
     
"lastName": "Doe"
   
},
   
{
     
"firstName": "Anna",
     
"lastName": "Smith"
   
},
   
{
     
"firstName": "Peter",
     
"lastName": "Jones"
   
}
 
],
 
"city": "Castle Rock",
 
"state": "Maine"
}

How would one go about getting the city of employees that have "Anna" as a first name?

Once again thanks a lot!

Tom Tran

unread,
Jul 7, 2016, 11:23:03 PM7/7/16
to jmeter-plugins, rafael.a...@gmail.com
Seems you wanna get the parent of matched element...

Hmmm, it's quite difficult to do it by JSON Extractor. However, I tried and there is some hope for you:

1. 
$..[?(@.employees[?(@.firstName == '${FIRST_NAME}')])].city

And this is the result: 

It looks like evaluating a condition inside other condition. You can change ${FIRST_NAME} variable by plain text "Anna" or whatever you want

2.
$..[?(@.employees[*].lastName == 'Smith')].city

This way is much more simple than the first one, but unfortunately, it doesn't work, JSON PATH might not parse
[*], I changed it to
$..[?(@.employees[1].lastName == 'Smith')].city

and it works well, but it's not useful when we must specific the value of employees object like employees[1]

Thanks,
Tom

On Thursday, July 7, 2016 at 11:39:36 PM UTC+7, rafael.a...@gmail.com wrote:

Rafael Anachoreta

unread,
Jul 8, 2016, 5:19:37 AM7/8/16
to Tom Tran, jmeter-plugins
Hi again, Tom!

You are spot on on what I am trying to achieve! 

I have tried to use your first expression, but it seems to return the City name no matter what I try to filter.
In other words, using:

$..[?(@.employees[?(@.firstName == 'InvalidName')])].city

..would still return Castle Rock, but that is not quite what I need.

Could this be a bug on JSON PATH?

Thank you!
Rafael

Tom Tran

unread,
Jul 8, 2016, 10:21:12 PM7/8/16
to jmeter-plugins, tuanv...@gmail.com, rafael.a...@gmail.com
Hi Rafael,

I'm not sure it's a bug of JSON Path Extractor or not. I hoped that someone else will help this case, because I also met problem with JSON Path, but not as your case.

Anyway, why don't you use the other way instead of JSON Path Extractor?

For example, using JSR233 along with Groovy (the best choice for scripting in JMeter). The code like that:

def first_name = vars.get("FIRST_NAME");
def slurper = new groovy.json.JsonSlurper();
def obj = slurper.parseText(prev.getResponseDataAsString());


def find_parent_element(obj,child){
 
for (int i = 0; i < obj.employees.size(); i ++) {
 
if (obj.employees[i].firstName == child) {
 
return obj.city
 
}
 
}
 
return "NOT_FOUND"
}


def city = find_parent_element(obj, first_name)


vars
.put("CITY", city)

Tom Tran

unread,
Jul 8, 2016, 10:30:55 PM7/8/16
to jmeter-plugins, tuanv...@gmail.com, rafael.a...@gmail.com
Hi Rafael,

I'm not sure it's a bug of JSON Path Extractor or not. I hoped that someone else will help this case, because I also met problem with JSON Path, but not as your case.

Anyway, why don't you use the other way instead of JSON Path Extractor?

For example, using JSR233 along with Groovy (the best choice for scripting in JMeter). The code like that:

def first_name = vars.get("FIRST_NAME");
def slurper = new groovy.json.JsonSlurper();
def obj = slurper.parseText(prev.getResponseDataAsString());

def find_parent_element(obj,child){
   
for (int i = 0; i < obj.employees.size(); i ++) {
       
if (obj.employees[i].firstName == child) {
           
return obj.city
       
}
   
}
   
return "NOT_FOUND"
}

def city = find_parent_element(obj, first_name)

vars
.put("CITY", city)



Where:
FIRST_NAME: is the variable of First Name (ex: Anna) which you defined somewhere in Thread Group, ex User Defined Variable
vars.put("CITY", city): will help you store local variable city into JMeter Variable named CITY, than you can call ${CITY} anywhere you want

The results:



You can try it by yourself, if you experience any issue, you can contact me again. I'll help you until you solve this problem.

Thanks,
Tom

rafael.a...@gmail.com

unread,
Jul 12, 2016, 11:28:16 AM7/12/16
to jmeter-plugins, tuanv...@gmail.com, rafael.a...@gmail.com
Hi again, Tom!

I chose to dive deep into the method you suggested, and I found it way easier to work with!
The flexibility given by the JSR233 sampler was exactly what I was looking for and with it I was able to solve all my problems for now :)
Plus, it has the upside of performing better than the BeanShell from what I've read!

My next step is figuring out how to properly work with the findAll() / recursive seach for maps on groovy, but I'll leave that for later since the loop you suggested is enough for now.

Thanks a lot for your resolve on helping me and all the good effort made!

Cheers,
Rafael

Tom Tran

unread,
Jul 13, 2016, 6:48:21 AM7/13/16
to jmeter-plugins, tuanv...@gmail.com, rafael.a...@gmail.com
You're welcome Rafael.
Reply all
Reply to author
Forward
0 new messages