Forum Discussion

nkpalli's avatar
nkpalli
Contributor
7 years ago

How to get keys from a nested array and check its existance using assertions

Trying to find solution on how we can  only just get all the  keys from a nested  JSON array object and check its existance using assertion?   Any pointer will be helpful as i find solutions where we can get keys using KeySet method but it only returns key 1, key 2, key 3, key 4 

 

Expected key values are :  key 1, key 2, key2.subKey 1, key2.subkey2, key2.subkey3,key2.subkey4, key 3, key 4 

 

 

 

Sample Json object :

 

 {
"id": "XYZ",
"errordetails": null,
"statuscode": 200,
"message": null,
"data": [
{

"key1": 1294,
"key2": [
       {
      "sub-key1: 0,
      "sub-key2": 2360,
      },
     {
       "sub-key3": 0,
       "sub-key4": 2820,
     }

           ],
"key3": true,
"key4": "3X2"
}

{
"Key1": 1294,
"key2": [
       {
      "sub-key1: 0,
      "sub-key2": 2360,
      },
     {
       "sub-key3": 0,
       "sub-key4": 2820,
     }

           ],
"key3": true,
"key4": "3X2"
}
]
}

  • nmrao's avatar
    nmrao
    Champion Level 3
    What are you trying to achieve? or your use case?
    • nkpalli's avatar
      nkpalli
      Contributor

      Hello

       

       

      Here is my Usecase:

       

      Send API request

      Get the API response  -

      Parse  JSON response 

      Get  keys from API response 

      And compare to expected if all the key attributes exist ( not comparing the values) using assertions 

       

       

       

  • JHunt's avatar
    JHunt
    Community Hero

    I had to tidy up your JSON for it to properly be parsed by SoapUI.

     

     

    {
       "id": "XYZ",
       "errordetails": null,
       "statuscode": 200,
       "message": null,
       "data":    [
                {
             "key1": 1294,
             "key2":          [
                            {
                   "sub-key1": 0,
                   "sub-key2": 2360
                },
                            {
                   "sub-key3": 0,
                   "sub-key4": 2820
                }
             ],
             "key3": true,
             "key4": "3X2"
          },
                {
             "Key1": 1294,
             "key2":          [
                            {
                   "sub-key1": 0,
                   "sub-key2": 2360
                },
                            {
                   "sub-key3": 0,
                   "sub-key4": 2820
                }
             ],
             "key3": true,
             "key4": "3X2"
          }
       ]
    }

    Here's my solution using a script assertion. It's probably a very round-about way of doing it. But it works.

     

    def expected = [
    "key1",
    "key2",
    "key2/sub-key1",
    "key2/sub-key2",
    "key2/sub-key3",
    "key2/sub-key4",
    "key3",
    "key4"
    ]

    def holder = new com.eviware.soapui.support.XmlHolder(messageExchange.responseContentAsXml)
    def exists = { it -> holder["count(//*:data//*:${it.replace("/", "//*:")})"].toString().toInteger() > 0 }
    expected.each {key -> assert exists(key) }

     

     

     

    • nkpalli's avatar
      nkpalli
      Contributor

      small clarification needed ,

       

      Looks like  syntax  provided in  below sample is used to  XML nodes right? since  the sample i send is a Json is there any corresponding code to read the Json nodes?


      JHunt wrote:

      I had to tidy up your JSON for it to properly be parsed by SoapUI.

       

       

      {
         "id": "XYZ",
         "errordetails": null,
         "statuscode": 200,
         "message": null,
         "data":    [
                  {
               "key1": 1294,
               "key2":          [
                              {
                     "sub-key1": 0,
                     "sub-key2": 2360
                  },
                              {
                     "sub-key3": 0,
                     "sub-key4": 2820
                  }
               ],
               "key3": true,
               "key4": "3X2"
            },
                  {
               "Key1": 1294,
               "key2":          [
                              {
                     "sub-key1": 0,
                     "sub-key2": 2360
                  },
                              {
                     "sub-key3": 0,
                     "sub-key4": 2820
                  }
               ],
               "key3": true,
               "key4": "3X2"
            }
         ]
      }

      Here's my solution using a script assertion. It's probably a very round-about way of doing it. But it works.

       

      def expected = [
      "key1",
      "key2",
      "key2/sub-key1",
      "key2/sub-key2",
      "key2/sub-key3",
      "key2/sub-key4",
      "key3",
      "key4"
      ]

      def holder = new com.eviware.soapui.support.XmlHolder(messageExchange.responseContentAsXml)
      def exists = { it -> holder["count(//*:data//*:${it.replace("/", "//*:")})"].toString().toInteger() > 0 }
      expected.each {key -> assert exists(key) }

       

       

       


       

      def holder = new com.eviware.soapui.support.XmlHolder(messageExchange.responseContentAsXml)

       

    • nkpalli's avatar
      nkpalli
      Contributor

      Hello team,

       

      I was able to look at the sample code suggestion and  i worked on my solution .

      However i get the script popup window which gives all the keys but not assertion passed message. How do i work it out into 

      this current script

       

      // Get API response
      def Response = context.expand( '${Validate Testcasename#Response}' )
      log.info(Response)
      def slurp = new groovy.json.JsonSlurper().parseText(Response)
      //verify the slurper isn't empty

      assert !(slurp.isEmpty())

      //Capture expected keys to match API reponse keys

      def expected =
      [
      "key1",
      "key2",
      "key2/sub-key1",
      "key2/sub-key2",
      "key2/sub-key3",
      "key2/sub-key4",
      "key3",
      "key4"
      ]
      def exists = { it -> slurp["count(//*:data//*:${it.replace("/", "//*:")})"].toString()}
      expected.each {key -> assert exists(key) }

       

       

       

       

  • JHunt's avatar
    JHunt
    Community Hero

    Hi,

     

    I think you are running this as a separate Groovy Script test step, but the script I posted was intended to be used as an assertion.

     

    Go to your Test Request and choose add assertion, and the type is Script Assertion.

     

    You can use my script exactly as is - you don't need to worry about XML vs JSON. The script gets the JSON response converted to XML: getResponseContentAsXml()

     

    When I tested it against the JSON response, it showed the assertion as passed.

     

     

    • nkpalli's avatar
      nkpalli
      Contributor

      Yeah..I  was adding separate groovy script ..

      Now i tried your way and i get this error :

       

      net.sf.saxon.trans.XPathException: XPath syntax error at char 15 on line 2 in {\ncount(//*:data//*:}: Whitespace and comments are not allowed after '*:'

  • JHunt's avatar
    JHunt
    Community Hero

    You might have a key name in your 'expected' that is not valid for XML. Have you changed it from the below?

     

    def expected = [
    "key1",
    "key2",
    "key2/sub-key1",
    "key2/sub-key2",
    "key2/sub-key3",
    "key2/sub-key4",
    "key3",
    "key4"
    ]

    Try taking out any keys that have spaces.