Dictionary Groovy映射点键到嵌套映射
我有一个带有点符号键的映射,但我需要它作为嵌套映射Dictionary Groovy映射点键到嵌套映射,dictionary,groovy,Dictionary,Groovy,我有一个带有点符号键的映射,但我需要它作为嵌套映射 [test.key.one: 'value1', text.key.two: 'value2'] 现在结果应该是 [ test: [ key: [ one: 'value1', two: 'value2' ] ] ] 这是我对代码的看法 def extract(String key, String value) { if(key.con
[test.key.one: 'value1', text.key.two: 'value2']
现在结果应该是
[
test: [
key: [
one: 'value1',
two: 'value2'
]
]
]
这是我对代码的看法
def extract(String key, String value) {
if(key.contains(".")) {
def (String target, String subKey) = key.split('\\.', 2)
return ["$target": extract(subKey, value)]
} else {
return ["$key": extractType(value)]
}
}
但是我想知道是否有groovy魔术在闭包中或者在其他好东西的帮助下使它更简单。有一个方便的类:
groovy.util.ConfigSlurper
def map = ['test.key.one': 'value1', 'test.key.two': 'value2']
def props = new Properties()
props.putAll(map)
println new ConfigSlurper().parse(props) // [test:[key:[two:value2, one:value1]]]
唯一的缺点是它需要
java.util.Properties
实例,因此您需要从map
创建一个实例,因为Dany的答案对我不起作用,我想支持类似Spring Boot的yaml解析,我的解决方案如下:
Map expandMapKeys(Map source) {
source.inject([:]) { result, key, value ->
if (value instanceof Map) value = expandMapKeys(value)
result + key.tokenize('.').reverse().inject(value) { current, token ->
[(token): current]
}
}
}
assert expandMapKeys([a: 'b']) == [a: 'b']
assert expandMapKeys([a: [b: 'c']]) == [a: [b: 'c']]
assert expandMapKeys(['a.b': 'c']) == [a: [b: 'c']]
assert expandMapKeys([a: ['b.c.d': 'e']]) == [a: [b: [c: [d: 'e']]]]
assert expandMapKeys(['a.b': 'c', 'a.d': 'e']) == [a: [d: 'e']] // not [a: [b: 'c', d: 'e'] !
注意最后一个断言:相同的父映射键将被覆盖。要解决这个问题,我们需要使用深度合并(我在互联网上找到)。此外,我们将处理一级列表,因为它们在yaml中也是可能的:
Map expandMapKeys(Map source) {
source.inject([:]) { result, key, value ->
if (value instanceof Map) value = expandMapKeys(value)
if (value instanceof Collection) value = value.collect { it instanceof Map ? expandMapKeys(it) : it }
merge(result, key.tokenize('.').reverse().inject(value) { current, token ->
[(token): current]
})
}
}
Map merge(Map[] sources) {
if (!sources) return [:]
if (sources.length == 1) return sources[0]
sources.inject([:]) { result, map ->
map.each { key, value ->
result[key] = result[key] instanceof Map ? merge(result[key], value) : value
}
result
}
}
assert expandMapKeys([a: 'b']) == [a: 'b']
assert expandMapKeys([a: [b: 'c']]) == [a: [b: 'c']]
assert expandMapKeys(['a.b': 'c']) == [a: [b: 'c']]
assert expandMapKeys([a: ['b.c.d': 'e']]) == [a: [b: [c: [d: 'e']]]]
assert expandMapKeys(['a.b': 'c', 'a.d': 'e']) == [a: [b: 'c', d: 'e']]
assert expandMapKeys([a: ['b.c': 'd'], e: [[f: ['g.h': 'i']], [j: ['k.l': 'm']]]]) == [a: [b: [c: 'd']], e: [[f: [g: [h: 'i']]], [j: [k: [l: 'm']]]]]