JSON Objects in SoapUI

In my last post I started looking at handling JSON response data in Groovy script using the JsonPathFacade class.  In the example I covered there, we checked to make sure all the countries returned in a response matched a search string-- each country entity returned had three properties: a 2 character code, a 3 character code, and a name.  Since the search string was so long (greater than three characters), we only had to check the name property of returned countries.  But what about a search on a shorter two-character string that could potentially match any of a given country's properties-- for example, what if our search string was "kh"?

Here's the corresponding response returned by the service:

{"RestResponse": {
   "messages":    [
      "More webservices are available at http://www.groupkt.com/post/f2129b88/services.htm",
      "Total [2] records found."
   ],
   "result":    [
            {
         "name": "Cambodia",
         "alpha2_code": "KH",
         "alpha3_code": "KHM"
      },
            {
         "name": "Kazakhstan",
         "alpha2_code": "KZ",
         "alpha3_code": "KAZ"
      }
   ]
}}


The method we used before to check names wouldn't work here-- Cambodia is only a match by virtue of its alpha codes, while Kazakhstan's only match is its name.  We have three string properties to check per country instead of one, so a simple one-dimensional array of strings isn't enough.  One approach we can take is to retrieve each country entity as a JSON object and check each object's set of properties.

Here's our new Groovy assertion (line numbers added by me for reference):

01  import com.eviware.soapui.support.JsonPathFacade
02
03  def failCount = 0
04  def jpf = new JsonPathFacade(messageExchange.responseContent)
05  def testArray = jpf.readObjectValue("RestResponse.result")
06  testArray.each {
07    def countryName = it.get("name")
08    def countryAlphaTwo = it.get("alpha2_code")
09    def countryAlphaThree = it.get("alpha3_code")
10    if(!countryName.toUpperCase().contains("KH") 
11      && !countryAlphaTwo.toUpperCase().contains("KH") 
12      && !countryAlphaThree.toUpperCase().contains("KH")) {
13   log.info("    Non-matching country: $countryName")
14   failCount++
15    }
16  } 
17  assert failCount == 0

I'll skip the first few lines (including the import statement and the creation of the failCount and jpf variables)-- these are the same as in the sample assertion from my last post.  The first difference is in line 5 where the readObjectValue() method is used with the JsonPathFacade object to retrieve the array of country entities (using the JsonPath expression RestResponse.result).  The resulting object assigned to the testArray variable is a JSONArray object from the net.sf.json library.  You can find more information about the library at http://json-lib.sourceforge.net.

Like the ListArray class in my last post, the JSONArray class is compatible with Groovy's each() method.  In line 6 it's called to step through the members of the JSONArray's collection of objects of the JSONObject class (also from the net.sf.json library).

The JSONObject class has a get() method that takes a property name and returns the corresponding property value.  In lines 7 through 9 the method is used to get the name, alpha2_code, and alpha3_code properties of each country object, assigning them to the countryName, countryAlphaTwo, and countryAlphaThree variables, respectively.

Once we've gotten the property values into variables, we can check them against our match string.  The if block's conditional statement is a bit gnarly; I've broken it up across lines 10 through 12.  It roughly translates to "if countryName, countryAlphaTwo, and countryAlphaThree do not contain the string 'KH'..."  Note that for each variable, I use the toUpperCase() method to convert all its characters to uppercase before applying the contains() method.  The contains() method is case sensitive, so converting to uppercase (including the match string) "normalizes" everything for easy comparison-- just as easily, I could have used the toLowerCase() method with the match string "kh".

The last few lines are similar to the last post: if the if conditional is true-- if we do indeed find a case where none of the country's properties contain the match string-- then we log information identifying the country (line 13) and increment the failCount variable by one (line 14).  Finally, after wrapping up our each block we assert that our failCount variable still equals zero after checking all the properties for all countries returned by the service.

No comments:

Post a Comment

Please be respectful of others (myself included!) when posting comments. Unfortunately, I may not be able to address (or even read) all comments immediately, and I reserve the right to remove comments periodically to keep clutter to a minimum ("clean" posts that aren't disrespectful or off-topic should stay on the site for at least 30 days to give others a chance to read them). If you're looking for a solution to a particular issue, you're free to post your question here, but you may have better luck posting your question on the main forum belonging to your tool's home site (links to these are available on the navigation bar on the right).