Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pull out nested Maps/EntrySets from JSON with Groovy when criteria met

Big trouble out in code-land and thus I am in need of help!

Using Groovy and JsonSlurper I am processing JSON of the form below. I am looking for the outside containing element (in my case this all SHOULD be Maps) when a "type" key is set to a certain value. For instance, if the type was "Type5", then I need to get three Maps back: the 'body' Map that contains the outer Type5, the 'body' Map that contains the INNER Type5, and the Type5 Map near the bottom (an EntrySet for each would work fine as well). Type3 and Type4 exhibit the same behavior!

Edited per request to have valid Json

I ran this through Groovy's JsonSlurper so it should be valid.

{
"type": "Run1",
"body": [
{
  "type": "Type1",
  "expression": {
    "type": "Type2",
    "expressions": [
      {
        "type": "Type3",
        "body": {
          "type": "Type4",
          "id": null,
          "params": [
            {
              "type": "Identifier",
              "name": "a"
            },
            {
              "type": "Identifier",
              "name": "b"
            },
            {
              "type": "Identifier",
              "name": "c"
            }
          ],
          "body": {
            "type": "Type5",
            "body": [
              {
                "type": "Type6",
                "id": {
                  "type": "Identifier",
                  "name": "d"
                },
                "params": [
                  {
                    "type": "Identifier",
                    "name": "a"
                  }
                ],
                "body": {
                  "type": "Type5",
                  "body": [
                    {
                      "type": "Type7",
                      "contents": {
                        "type": "Type8",
                        "leftcontents": {
                          "type": "Literal",
                          "value": "specific name",
                        },
                        "rightcontents": {
                          "type": "Type3",
                          "body": {
                            "type": "Type4",
                            "object": {
                              "type": "Identifier",
                              "name": "o"
                            },
                            "property": {
                              "type": "Identifier",
                              "name": "f"
                            }
                          },
                          "contents": [
                            {
                              "type": "Identifier",
                              "name": "a"
                            }
                          ]
                        }
                      }
                    }
                  ]
                },
              },
              {
                "type": "Type6",
                "id": {
                  "type": "Identifier",
                  "name": "e"
                },
                "params": [
                  {
                    "type": "Identifier",
                    "name": "a"
                  }
                ],
                "defaults": [],
                "body": {
                  "type": "Type5",
                  "body": [
                    {
                      "type": "Type7",
                      "contents": {
                        "type": "Type8",
                        "leftcontents": {
                          "type": "Literal",
                          "value": "string",
                        },
                        "rightcontents": {
                          "type": "Type9",
                          "argument": {
                            "type": "Identifier",
                            "name": "a"
                          },
                          "prefix": true
                        }
                      }
                    }
                  ]
                },
              }
            ]
          }
        }
      }
    ]
  }
}
]
}

I am just doing this:

FileInputStream fis = new FileInputStream('myInput.json')
def jsonData = (new JsonSlurper()).parse(fis)

although I can readily access individual parts of the structure, to get all the "Type5"s that have arbitrary nesting levels is beyond me. Can anyone shine some brilliance on this?

like image 341
JoeG Avatar asked Jan 22 '15 18:01

JoeG


1 Answers

Basically you would collect all maps and recurse on collections and on all map values. E.g.:

def json='{"type":"Run1","body":[{"type":"Type1","expression":{"type":"Type2","expressions":[{"type":"Type3","body":{"type":"Type4","id":null,"params":[{"type":"Identifier","name":"a"},{"type":"Identifier","name":"b"},{"type":"Identifier","name":"c"}],"body":{"type":"Type5","body":[{"type":"Type6","id":{"type":"Identifier","name":"d"},"params":[{"type":"Identifier","name":"a"}],"body":{"type":"Type5","body":[{"type":"Type7","contents":{"type":"Type8","leftcontents":{"type":"Literal","value":"specificname",},"rightcontents":{"type":"Type3","body":{"type":"Type4","object":{"type":"Identifier","name":"o"},"property":{"type":"Identifier","name":"f"}},"contents":[{"type":"Identifier","name":"a"}]}}}]},},{"type":"Type6","id":{"type":"Identifier","name":"e"},"params":[{"type":"Identifier","name":"a"}],"defaults":[],"body":{"type":"Type5","body":[{"type":"Type7","contents":{"type":"Type8","leftcontents":{"type":"Literal","value":"string",},"rightcontents":{"type":"Type9","argument":{"type":"Identifier","name":"a"},"prefix":true}}}]},}]}}}]}}]}'
def slrp = new groovy.json.JsonSlurper().parseText(json)

def collectMaps(e) {
    e.with{
        if (it instanceof Map) {
            [it] + it.values().collect{ collectMaps(it) }
        } else if (it instanceof Collection) {
            it.collect{ collectMaps(it) }
        } else {
            []
        }
    }.flatten()
}

assert collectMaps(slrp).findAll{ it.type=='Type5' }.size()==3
assert collectMaps(slrp).findAll{ it.type=='Type3' }.size()==2
like image 159
cfrick Avatar answered Nov 08 '22 08:11

cfrick