LoadRunner and Performance Center Blog
cancel

Get a new way to manipulate JSON with load testing in LoadRunner

Get a new way to manipulate JSON with load testing in LoadRunner

Micro Focus Expert

 Learn about the capabilities in the latest version of LoadRunner 

Ellie.png

This post was written by Ellie Yang, from the Protocols core team

 

 

 

JavaScript Object Notation (JSON) is a lightweight data-interchange format. It is an easier alternative to use than the common XML, and is used widely in the web world. As its name indicates, JSON conveniently works with the JavaScript language script.


LoadRunner load testing software supports JavaScript as scripting language since release 12.50, however if a user wants to manipulate JSON within an existing C-script, this is more challenging. In previous versions of LoadRunner (prior to 12.53), the User has a choice either to use DFE Convert it to XML, applying XML functions on it, or to take JSON as string, and use C-string functions to find/edit the necessary changes. 

Try LoadRunner load testing software for yourself here for free.

 LoadRunner12.53 introduces a series of new APIs to manipulate JSON in C language script, making the scripting process easier and quicker for the script developers.

To demonstrate LoadRunner’s new capabilities, we will use the following JSON example:

{
    "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 **bleep**",
                "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
        }
    }
}

Supposing the JSON content has been saved in parameter file JSON_Content, to get the titles of all the books, we will use the following script:  

// Load JSON
    lr_eval_json("Buffer={JSON_Content}",
                 "JsonObject=json_obj"LAST);    

    // Save result in parameter "title"
    lr_json_get_values("JsonObject=json_obj",
                       "ValueParam=title",
                       "QueryString=$.store.book[*].title",
                       LAST);

We can see the results saved in parameter {title} via the log file:

Action.c(20): Notify: Saving Parameter "title_1 = Sayings of the Century".
Action.c(20): Notify: Saving Parameter "title_2 = Sword of Honour".
Action.c(20): Notify: Saving Parameter "title_3 = Moby **bleep**".
Action.c(20): Notify: Saving Parameter "title_4 = The Lord of the Rings".
Action.c(20): Notify: Saving Parameter "title_count = 4".
Action.c(20): lr_json_get_values succeed, 4 matches

This capability is quite simple—as shown above.

To manipulate JSON, just follow the following steps: 

[1] Load JSON

lr_eval_json is always the first API to call, it creates a JSON object either from a string or from a file.

From a string:

    lr_eval_json("Buffer={JSON_Content}",
                 "JsonObject=json_obj"LAST);

From a file:

    lr_eval_json("Buffer/File=store.json",
                 "JsonObject=json_obj"LAST);

[2] Edit JSON

After the JSON object is created, LoadRunner supplies the following APIs to edit the JSON object:

lr_json_insert
lr_json_delete
lr_json_replace
lr_json_set_values 

We can recognize the functionality of these APIs from their informative names.

All these APIs get an argument "JsonObject" which should be the JSON object created using lr_eval_json.

Another important argument is "QueryString", it is a path addressing the parts of the JSON object, which uses JSONPath language. The grammar of JSONPath is similar as Xpath. It has already been used in JSON correlation API web_reg_save_param_json introduced by LoadRunner 12.50.

To learn the basics and find more examples about JSONPath, read here.

Still using the JSON above as our example, if we want to add an "owner” field for this store, we could do:

lr_json_insert("JsonObject=json_obj",
               "Value={\"owner\":\"Mr. Black\"}",
               "QueryString=$.store",
               LAST); 

If we would like to add a new book, it would be done as:

lr_json_insert("JsonObject=json_obj",
               "Value=[{\"category\":\"fiction\",\"author\":\"Harper Lee\",\"title\": \"To Kill a Mockingbird\",\"price\":8.99}]",
               "QueryString=$.store.book",
               LAST);

Please note the argument Value.  
In the first example, owner is wrapped as a JSON object while the target element ($.store) is an Object.   In the second example the new book is put in a JSON array while the target element ($.store.book) is an array.
That is the rule of lr_json_insert():  the new element and the target element must have the same type, both being an object or an array. Basically, this can be considered as a merge.

To delete the "bicycle" from the store, we could call:

lr_json_delete("JsonObject=json_obj",
               "QueryString=$.store.bicycle",
               LAST);

Viola!…Now it is a book store that sells  books only!

In our example, as some books are too reduced, we would like to raise the price of these books. :

lr_json_set_values("JsonObject=json_obj",
                   "Value=9.99",
                   "QueryString=$.store.book[?(@.price < 9.99)].price",
                   "SelectAll=Yes",
                   LAST); 

For those books that have "isbn", we would like to delete this field and replace it with "discount".

lr_json_replace("JsonObject=json_obj",
                "Value=\"discount\":\"20 percent\"",
                "QueryString=$.store.book[*].isbn",
                "SelectAll=Yes",
                LAST); 

Please note the difference between lr_json_set_values() and lr_json_replace().
 In  lr_json_set_values, we only changed the value in the key-value pair, and for lr_json_replace, the key has also been replaced. 

All these change will be applied on the specified JSON object. Meaning the user could load the JSON just once, do a series of changes, then output to see the final results.

This is different from LoadRunner xml functions. 

[3]. Query

lr_json_get_values and lr_json_find are two query APIs that don't make changes to the JSON object. We've already seen how lr_json_get_values works. Now let's check lr_json_find.

lr_json_find returns the number of matches to a query.

If we want to discover how many books were written by Tolkien, we could ask:

i = lr_json_find("JsonObject=json_obj",
                "Value=.*Tolkien",
                "QueryString=$.book[*].author",
                "UseRegExp=Yes",
                LAST); 

[4]. Output modified JSON

After all of the modifications we’ve performed, we can use the lr_json_stringify to get the result:

lr_json_stringify("JsonObject=json_obj",
                                  "OutputParam=result",
                                LAST);

This function converts the JSON object to a JSON string, and saves it in parameter "{Result}".

Going back to our example, the bold parts shows the changes we made to our initial model:

{
    "store": {
        "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 9.99
            },
            {
                "category": "fiction",
                "author": "Evelyn Waugh",
                "title": "Sword of Honour",
                "price": 12.99
            },
            {
                "category": "fiction",
                "author": "Herman Melville",
                "title": "Moby **bleep**",
                "discount": "20 percent",
                "price": 9.99
            },
            {
                "category": "fiction",
                "author": "J. R. R. Tolkien",
                "title": "The Lord of the Rings",
                "discount": "20 percent",
                "price": 22.99
            },
            {
                "category": "fiction",
                "author": "Harper Lee",
                "title": "To Kill a Mockingbird",
                "price": 9.99
            }
        ],
        "owner" : "Mr. Black"
    }

To summarize, the new JSON APIs family enhances usability and ease of the LoadRunner C script.
It will save time spent on editing existing scripts, however it may not be as intuitive as using JSON in the natural JavaScript language, but provides more possibilities with JsonPath support.

We urge you to try out this added capability and check out the LoadRunner Help Center and 12.53 documentation for full details on this feature. Enjoy!

You can try LoadRunner load testing software for yourself here for free.

A special thanks to Ellie from the Protocols core R&D team for providing this instructive article.

 

 

 

Comments
Absent Member.

Dear team,

These are handful APIs which will be very useful when working with JSON and saves a lot of time, since I know how hard it is to work with JSON data without these APIs in the lower versions of LoadRunner.

I have a query here. The JSON data that we took for example is a very simple one. In many real time scenarios, the depth of the JSON object that we have to deal with is very high and I am wondering will these functions work in that case? 

For example - the XPath of the object in question is this deep will all these APIs work ?  /HP_EXTENSION[1]/array[1]/object[4]/array[1]/object[1]/pair[1]/text()[1]

 

Also I would like to know if there are APIs to compare two JSON response strings to identify if there are any changes/differences in the response from what was recorded. 

 

Thanks.

Absent Member..

The recording engine is capable of generate automatically the JSON commands through the script generation or they can be used manually just by customizing the code?