venturieffect
venturieffect

Reputation: 191

Default values on nested maps in Groovy

I have a JSON configuration file that I want to read with groovy this file has "defaults" in case one key would be missing because no specific configuration has been added.

json

{
  "presets": {
    "default": "preset_default",
    "Team1":{
      "AppName1":{
        "Component1": "preset_team1App1Comp1",
        "default" : "preset_team1App1Default"
      },
      "AppName2":{
        "Component1": "preset_team1App2Comp1",
        "Component2": "preset_team1App2Comp2"
      },
      "default" : "preset_team1Default"
    },
    "Team2":{
      "AppName1":{
        "Component1": "preset_team2App1Comp1"
      }
    }
  }
}

What would be the most groovy way to search for the value and falling back to the outer most "default" key? here's how I implemented it but I'm not sure this would work:

if (presets[appTeam])
    if (presets[appTeam][appName])
        if (presets[appTeam][appName][compName])
            this.preset = presets[appTeam][appName][compName]
        else
            this.preset = presets[appTeam][appName]['default']
    else
        this.preset = presets[appTeam]['default']
else
    this.preset = presets['default']

Thank you in advance

Upvotes: 1

Views: 189

Answers (3)

daggett
daggett

Reputation: 28564

another way


def value(presets, team, app, compt) {
    def defkey = 'default'
    return presets.get(team)?.get(app)?.get(compt) ?: 
           presets.get(team)?.get(app)?.get(defkey) ?:
           presets.get(team)?.get(defkey) ?:
           presets.get(defkey)
}

assert value(presets, 'TeamUnknown', "AppName2", "Component14") == 'preset_default'
assert value(presets, 'Team1', "AppName2", "Component14") == 'preset_team1Default'
assert value(presets, 'Team1', "AppName2", "Component1") == 'preset_team1App2Comp1'

Upvotes: 1

injecteer
injecteer

Reputation: 20699

A simple generic recursion would help:

def input = new groovy.json.JsonSlurper().parseText '''{
  "presets": {
    "default": "preset_default",
    "Team1":{
      "AppName1":{
        "Component1": "preset_team1App1Comp1",
        "default" : "preset_team1App1Default"
      },
      "AppName2":{
        "Component1": "preset_team1App2Comp1",
        "Component2": "preset_team1App2Comp2"
      },
      "default" : "preset_team1Default"
    },
    "Team2":{
      "AppName1":{
        "Component1": "preset_team2App1Comp1"
      }
    }
  }
}'''


def findRecursive
findRecursive = { json, List keys, List defaults = [] ->
  if( !json || ( json in String ) || !keys ) return json
  if( json.default ) defaults << json.default
  findRecursive json[ keys.remove( 0 ) ] ?: defaults.last(), keys, defaults
}

assert 'preset_team1App1Comp1' == findRecursive( input.presets, [ 'Team1', 'AppName1', 'Component1' ] )
assert 'preset_team2App1Comp1' == findRecursive( input.presets, [ 'Team2', 'AppName1', 'Component1' ] )
assert 'preset_team1Default' == findRecursive( input.presets, [ 'Team1', 'AppName3', 'Component1' ] )
assert 'preset_default' == findRecursive( input.presets, [ 'Team3' ] )
assert 'preset_default' == findRecursive( input.presets, [ 'Team2', 'AppName2', 'Component1' ] )

Upvotes: 1

tim_yates
tim_yates

Reputation: 171054

One way would be to use "inject" to walk along your keys, and keep track of the latest default seen... Something like this:

def value(Map presets, String... keys) {
    keys.inject([pos: presets, result: presets.default]) { latest, current ->
        def node = latest.pos[current]

        if (node instanceof Map) {
            [pos: node, result: node.default ?: latest.result]
        } else if (node instanceof String) {
            [pos: node, result: node]
        } else if (node == null) {
            [pos: node, result: latest.result]
        } else {
            throw new RuntimeException("No idea what to do with a ${node.class.simpleName}")
        }
    }.result
}

Then you can do (with the above example)

// Defaults
assert value(presets, 'TeamUnknown', "AppName2", "Component14") == 'preset_default'
assert value(presets, 'Team1', "AppName2", "Component14") == 'preset_team1Default'

// Values
assert value(presets, 'Team1', "AppName2", "Component1") == 'preset_team1App2Comp1'

Upvotes: 2

Related Questions