Groovy 中嵌套地图的默认值

Default values on nested maps in Groovy

我有一个 JSON 配置文件,我想用 groovy 读取 此文件具有“默认值”,以防因未添加特定配置而丢失一个键。

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"
      }
    }
  }
}

最 groovy 搜索值并回退到最外层“默认”键的方法是什么? 这是我的实现方式,但我不确定这是否可行:

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']

提前致谢

一种方法是使用“注入”来遍历您的密钥,并跟踪看到的最新默认设置...像这样:

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
}

然后就可以了(用上面的例子)

// 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'

一个简单的通用递归会有所帮助:

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' ] )

另一种方式


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'