1

My end goal is to parse thru an unknown .json file stored on my laptop and get the key names (not the values only key names) using Groovy in SoapUI.

I want to parse an unknown JSON file stored in my computer and get its keys (name of the keys, not the values). I can do 2 things separately:

  1. I am able to read the local JSON using the following code I found online:

    def JSON_URL = "file:///C:/Users/xxx/example.json"    
    URL url = new URL(JSON_URL)
    InputStream urlStream = null
    
         try {
          urlStream = url.openStream()
          BufferedReader reader = new BufferedReader(new Inpu   tStreamReader(urlStream))
          JsonSlurper js1 = new JsonSlurper()
          Object result = js1.parse(reader)
          log.info "==> readJSONfile2 result of read: "+result
    } catch (Exception e) {
        log.info e
    }
    
  2. And if I have the URL, I am able to parse it and get keys like so:

    // getting the response
    
    def resp1 = context.expand('${testStepName#response}')
    

    // parsing the set context

    def js1 = new JsonSlurper().parseText(resp1)
    
    def keys = js1.entrySet() as List
    
    log.info "==> runTreatmentPlan keys list is: "+keys
    
    log.info "==> runTreatmentPlan keys size is: "+keys.size()
    

But I am unable to get the keys if the JSON is local to my machine ie unable to combine both the codes. I get error when I do:

Object result = js1.parseText(reader) 

I am new to groovy and SoapUI and json - a total newbie and this is my first question. I am really scared because I have seen that some people are kinda rough towards other newbies if the question is basic. I promise, I did google a lot, and I am sure the experienced people might find my question stupid as well, but I am really stuck. I am unable to combine both pieces of code. I kinda feel that I will some how have to use the response from #1 code, but I don't know how. Can someone help me please?

==== Updating with the JSON structure:

{
  "Key0": [
    {
      "Key1": "Value1",
      "Key2": "Value2",
      "Key3": "Value3",
      "Key4": {
        "subKey1": "subValue1"
      },
      "Key5": {
        "subKey1": "subValue1",
        "subKey2": "subValue2",
        "subKey3": "subValue3",
        "subKey4": "subValue4"
      },
      "Key6": "2016-07-11T17:52:59.000Z",
      "Key7": [
        {
          "subKey1": "subValue1",
          "subKey2": "subValue2"
        },
        {
          "subKey1": "subValue1",
          "subKey2": "subValue2"
        },
        {
          "subKey1": "subValue1",
          "subKey2": "subValue2"
        },
        {
          "subKey1": "subValue1",
          "subKey2": "subValue2"
        }
      ]
    },
    {
      "Key1": "Value1",
      "Key2": "Value2",
      "Key3": "Value3",
      "Key4": {
        "subKey1": "subValue1"
      },
      "Key5": {
        "subKey1": "subValue1",
        "subKey2": "subValue2",
        "subKey3": "subValue3",
        "subKey4": "subValue4"
      },
      "Key6": "2016-07-11T17:52:59.000Z",
      "Key7": [
        {
          "subKey1": "subValue1",
          "subKey2": "subValue2"
        },
        {
          "subKey1": "subValue1",
          "subKey2": "subValue2"
        },
        {
          "subKey1": "subValue1",
          "subKey2": "subValue2"
        },
        {
          "subKey1": "subValue1",
          "subKey2": "subValue2"
        }
      ]
    }
  ]
}
Rao
  • 20,781
  • 11
  • 57
  • 77
Jigs
  • 21
  • 4
  • What is your use case? And see if [this](http://stackoverflow.com/questions/23654646/groovy-how-do-i-search-json-with-keys-value-and-find-its-children-in-groovy) is what you looking for? – Rao Aug 26 '16 at 14:20
  • Thank you for the response Rao, but this is not what I am looking for ... mor elike what @dmahapatro is saying ... – Jigs Aug 26 '16 at 16:18
  • Likely depends on what you wanted to do after getting the keys. Because, `entrySet()` will only get the immediate properties. If a property is complex, then you have to loop thru it. There can be array as well, so it wont be much useful toget keys into linear from hierarchal. That is why I was asking what is your use case after reading an arbitrary json? – Rao Aug 27 '16 at 01:37
  • @Jigs See my updated answer. I believe that is what you are looking for. – dmahapatro Aug 27 '16 at 15:05
  • @dmahapatro, please see my update below .... – Jigs Aug 28 '16 at 01:30

2 Answers2

3

Given your input, this code:

import groovy.json.JsonSlurper

def traverse
traverse = { tree, keys = [], prefix = '' ->
    switch (tree) {
        case Map:
            tree.each { k, v -> 
                def name = prefix ? "${prefix}.${k}" : k
                keys << name
                traverse(v, keys, name)
            }
            return keys
        case Collection:
            tree.eachWithIndex { e, i -> traverse(e, keys, "${prefix}[$i]") }
            return keys
        default :
            return keys
    }
}

def content = new JsonSlurper().parse( new File( 'sample.json' ) )

traverse(content).each { println it }

Yields this output:

Key0
Key0[0].Key1
Key0[0].Key2
Key0[0].Key3
Key0[0].Key4
Key0[0].Key4.subKey1
Key0[0].Key5
Key0[0].Key5.subKey1
Key0[0].Key5.subKey2
Key0[0].Key5.subKey3
Key0[0].Key5.subKey4
Key0[0].Key6
Key0[0].Key7
Key0[0].Key7[0].subKey1
Key0[0].Key7[0].subKey2
Key0[0].Key7[1].subKey1
Key0[0].Key7[1].subKey2
Key0[0].Key7[2].subKey1
Key0[0].Key7[2].subKey2
Key0[0].Key7[3].subKey1
Key0[0].Key7[3].subKey2
Key0[1].Key1
Key0[1].Key2
Key0[1].Key3
Key0[1].Key4
Key0[1].Key4.subKey1
Key0[1].Key5
Key0[1].Key5.subKey1
Key0[1].Key5.subKey2
Key0[1].Key5.subKey3
Key0[1].Key5.subKey4
Key0[1].Key6
Key0[1].Key7
Key0[1].Key7[0].subKey1
Key0[1].Key7[0].subKey2
Key0[1].Key7[1].subKey1
Key0[1].Key7[1].subKey2
Key0[1].Key7[2].subKey1
Key0[1].Key7[2].subKey2
Key0[1].Key7[3].subKey1
Key0[1].Key7[3].subKey2
BalRog
  • 3,216
  • 23
  • 30
  • PURRRFECCCTTTTTTT ... This is what I was looking for !! I just had to update the parser line like so: def content = new JsonSlurper().parse**Text** ( new File('C:/Users/example.json') **.text**) ... I did upvote your answer, but since I am a newbie, my vote did not increase the rating of you answer =/ – Jigs Aug 31 '16 at 03:21
0
import groovy.json.JsonSlurper

/**
 * sample.json present in C:/tools/
 * { "foo": "bar", "baz": 123 }
 */
def content = new JsonSlurper().parse( new File( 'C:/tools/sample.json' ) )

assert content.keySet() == ['baz', 'foo'] as Set

UPDATE:
After looking at the actual json structure and the issues with the version of Groovy in SOAPUI, below would be a viable option to get all the keys in a specific format:

import groovy.json.JsonSlurper

def textFromFile = new File('/path/to/example.json').text
def content = new JsonSlurper().parseText(textFromFile)

def getAllKeys(Map item) {
    item.collect { k, v ->
        v instanceof Map ? convertToString(v).collect { "${k}.$it" } : k
    }.flatten() 
}

assert getAllKeys(content) == [
 'Key1', 'Key2', 'Key3', 
 'Key4.subKey1', 'Key5.subKey1', 'Key5.subKey2', 
 'Key5.subKey3', 'Key5.subKey4', 
 'Key6', 'Key7'
]
dmahapatro
  • 49,365
  • 7
  • 88
  • 117
  • Thank you dmahapatro, this code is throwing error: groovy.lang.MissingMethodException: No signature of method: groovy.json.JsonSlurper.parse() is applicable for argument types: (java.io.File) values: [C:\Users\example.json] – Jigs Aug 26 '16 at 16:19
  • Which version of Groovy are you using? Is the version less than 2.2.0? http://docs.groovy-lang.org/latest/html/gapi/groovy/json/JsonSlurper.html#parse(java.io.File) – dmahapatro Aug 26 '16 at 16:22
  • Seems the free SoapUI version that I have is using 2.1.7 (groovy-all-2.1.7.jar) – Jigs Aug 26 '16 at 16:38
  • Since you are using free version of SoapUI, it will be easier to upgrade to the latest version. Upgrade to the latest version where newer and better groovy API's will be available for use. – dmahapatro Aug 26 '16 at 16:43
  • I do have latest 'FREE' version 5.2.1 and unfortunately it uses old version of everything. I tried replacing old groovy jar 2.1.7 with newer 2.3.10 n the bin folder, but SoapUI hung ... refused to even start (obviously) ... – Jigs Aug 26 '16 at 17:07
  • This is no different from @albciff answer and does not work for complex json. – Rao Aug 27 '16 at 01:31
  • @Rao Please showcase an example where it does not work and it is different from Albciff's answer, if you look closely. However, albciff's answer was deleted when this answer was submitted. So it will be much more helpful if a breaking example is present. – dmahapatro Aug 27 '16 at 02:07
  • @Rao my answer was deleted when @dmahapatro post his one. I undeleted the answer erroniusly and now I deleted again until I can will review it `:)`. sorry guys for this confusion. – albciff Aug 27 '16 at 18:26
  • @dmahapatro it gave me a long string ... I found this a little more useful: import groovy.json.JsonSlurper def fileTxt = new File("C:/Users/example.json").getText('UTF-8') def js1 = new JsonSlurper().parseText(fileTxt) for (String temp1 : js1.keySet()) { log.info temp1 } log.info "---------------------------------------" for (String temp2 : js1.treatmentPlans[0].keySet()) { log.info temp2 } – Jigs Aug 28 '16 at 01:35
  • I think using this code, I need to itirate thru the value for the 1st string - temp1 ... I did not find the way to collect the value only yet ... still googling So, I built upon ur solution and since I am getting the 1st string as value that has nested arrays, I will then iterate using if clause ... makes sense? Also, do u know how to get just the value part of the key? – Jigs Aug 28 '16 at 01:36