Parsing nested JSON in groovy

2 answers

I would like to parse the below nested JSON in Groovy and get the values of "it","ft","stg","prd" for each application and store in separate array.Can someone help please ?

    {         "Application1": {             "environments": {                 "it": [                     "server1"                 ],                 "ft": [                     "server2"                 ],                 "stg": [                     "server3"                 ],                 "prd": [                     "server4"                 ]             },             "war-path" : "/opt/tomcat/",             "war-name" : "Application1"         },         "Application2": {             "environments": {                 "it": [                     "serverA"                 ],                 "ft": [                     "serverB"                 ],                 "stg": [                     "serverC"                 ],                 "prd": [                     "serverD"                 ]             },             "war-path" : "/var/lib",             "war-name" : "Application2"         }     } } 

Expected output something like below in separate list for each environment. Also the 1st level(Application1,Application2..) will be dynamic always

it = [server1,serverA] ft = [server2,serverB] stg = [server3, serverC] prd = [server4,serverD] 

Updated: After deriving expected answer with the inputs from Philip Wrage.

def projects = readJSON file: "${env.WORKSPACE}//${infrafile}" def json_str = JsonOutput.toJson(projects) def json_beauty = JsonOutput.prettyPrint(json_str) def envlist = ["it","ft","stg","prd"] def fileListResult = []   for (envname in envlist) {     servers=serverlist(json_beauty,envname)     println(servers) }  def serverlist(json_beauty,envname){     def jsonSlurper = new JsonSlurper()     def jsonMap = jsonSlurper.parseText(json_beauty)      assert jsonMap instanceof Map     jsonMap.each { appName, appDetails ->          assert appDetails instanceof Map         appDetails.environments.each { envName, servers ->             for (items in servers{                 if (envName == "${envname}"){                     fileListResult.add(items)                 }             }         }             }     return fileListResult } 

All answers to this question, which has the identifier 60729969

The best answer:

As suggested by @Chris, you can use the built-in JsonSlurper to parse the JSON and then navigate the parsed results as a Map.

In the following example I show how you can simply print the results to the console. However, using this as a guide, you can see how to extract the data into whatever kind of data structure that suits your purpose.

Assume that you have the JSON in a String variable jsonText. You may be pulling in from a file or an HTTP POST or whatever your app requires. I used the following code to set this value for testing.

def jsonText = """ {     "Application1": {     "environments": {         "it": [                 "server1"         ],         "ft": [                 "server2"         ],         "stg": [                 "server3"         ],         "prd": [                 "server4"         ]     },     "war-path" : "/opt/tomcat/",     "war-name" : "Application1" },     "Application2": {     "environments": {         "it": [                 "serverA"         ],         "ft": [                 "serverB"         ],         "stg": [                 "serverC"         ],         "prd": [                 "serverD"         ]     },     "war-path" : "/var/lib",     "war-name" : "Application2" } } """ 

The meat of the solution then follows. Parse the JSON text into a Map, and then iterate over the entries in that Map, performing whatever operations you require. The servers for each environment will already be contained within a List.

import groovy.json.JsonSlurper  def jsonSlurper = new JsonSlurper() def jsonMap = jsonSlurper.parseText(jsonText)  assert jsonMap instanceof Map  jsonMap.each { appName, appDetails ->     println "Application: $appName"     assert appDetails instanceof Map     appDetails.environments.each { envName, servers ->         assert servers instanceof List         println "\tEnvironment: $envName"         println "\t\t$servers"     } } 

From this code I obtain the following console output.

Application: Application1     Environment: it         [server1]     Environment: ft         [server2]     Environment: stg         [server3]     Environment: prd         [server4] Application: Application2     Environment: it         [serverA]     Environment: ft         [serverB]     Environment: stg         [serverC]     Environment: prd         [serverD] 

EDIT (based on clarification of required output):

import groovy.json.JsonSlurper  def jsonText = "\n{\n    \"Application1\": {\n    \"environments\": {\n        \"it\": [\n                \"server1\"\n        ],\n        \"ft\": [\n                \"server2\"\n        ],\n        \"stg\": [\n                \"server3\"\n        ],\n        \"prd\": [\n                \"server4\"\n        ]\n    },\n    \"war-path\" : \"/opt/tomcat/\",\n    \"war-name\" : \"Application1\"\n},\n    \"Application2\": {\n    \"environments\": {\n        \"it\": [\n                \"serverA\"\n        ],\n        \"ft\": [\n                \"serverB\"\n        ],\n        \"stg\": [\n                \"serverC\"\n        ],\n        \"prd\": [\n                \"serverD\"\n        ]\n    },\n    \"war-path\" : \"/var/lib\",\n    \"war-name\" : \"Application2\"\n}\n}\n"  def jsonSlurper = new JsonSlurper() def jsonMap = jsonSlurper.parseText(jsonText)  def result = [:]  jsonMap.each { appName, appDetails ->     appDetails.environments.each { envName, servers ->         if ( !result.containsKey(envName) ) {             result.put(envName, [])         }         result.get(envName).addAll(servers)     } } println result 

Results are a Map where the keys are the various environments specified within JSON file, and the values are Lists of servers associated with those environments across all applications. You can access any List individually with something like result.stg, or assign these the different variables later if that's desired/required (def stg = result.stg).

[it:[server1, serverA], ft:[server2, serverB], stg:[server3, serverC], prd:[server4, serverD]] 

If you want all environments, you can use the spread operator to take all environments from the values. Next you have to merge the maps on the keys. E.g.

def json = """ { "Application1": { "environments": { "it": [ "server1" ], "ft": [ "server2" ], "stg": [ "server3" ], "prd": [ "server4" ] }, }, "Application2": { "environments": { "it": [ "serverA" ], "ft": [ "serverB" ], "stg": [ "serverC" ], "prd": [ "serverD" ] }, } } }"""  def data = new groovy.json.JsonSlurper().parseText(json)  println data.values()*.environments.inject{ a, b ->      b.inject(a.withDefault{[]}) { m, kv ->          // with groovy 2.5+: m.tap{ get(kv.key).addAll(kv.value) }         m[kv.key].addAll(kv.value); m     }  } // → [it:[server1, serverA], ft:[server2, serverB], stg:[server3, serverC], prd:[server4, serverD]] 

Last questions

how do i remove the switch on my home screen?
how to edit the JS date and time to update atuomatically?
How to utilize data stored in a multidimensional array
Powermockito not mocking URL constructor in URI.toURL() method
Android Bluetooth LE Scanner only scans when phone's Location is turned on in some devices
docker wordpress container can't connect to mysql container
How can I declare a number in java that is more than 64-bits? [duplicate]
Optaplanner solutionClass entityCollectionProperty should never return null error when simple JSON object passed to controller
Anylogic, get the time a pedestrain is in a queue
How do I fix this syntax issue with my .flex file?
Optimizing query in PHP
How to find the highest number of a column and print two columns of that row in R?
Ideas on “Error: Type com.google.firebase.iid.zzav is referenced as an interface from com.google.firebase.messaging.zzd”?
JCIFS SmbFile.exists() and SmbFile.isDirectory() return false when it exists and I can listFiles()
PHP total order
Laravel booking system design
neural net - undefined column selected
How to indicate y axis does not start from 0 in ggplot?
Fragments in backStack
Spinner how to change the data