给定Groovy中的嵌套地图/列表/标量数据结构,它是否有任何漂亮的“ Groovy”方式来遍历它并生成转换后的结构?
到目前为止,我编写的最干净的方法还不错,这是一个使用闭包的递归walker。但是,如果有一种我想念的内置方式,我欢迎提出建议。
例如,采用此数据结构,并在其中的${VARIABLE}
s中将REPLACED
的所有实例替换为String
:
def config = [
'${VARIABLE}: 'scalar',
'foo': [
'bar': 1,
'baz': ['a', 'b', 'c', 'd'],
'my_${VARIABLE}_key': null
],
'bak': 1,
'ban': 'abcd',
'boo': [
['x': 1, 'y': 2, 'subst': '${VARIABLE}'],
['a': 1, 'b': 2]
]
]
答案 0 :(得分:0)
这是到目前为止我想出的最好的方法:
def walk(v, Closure transform ) {
switch (v) {
case null:
return null
case Map:
return v.collectEntries { mk, mv -> [ transform(mk), walk(mv, transform) ] }
case List:
return v.collect { lv -> walk(lv, transform) }
default:
return transform(v)
}
}
给出上述示例数据的可能会这样应用:
def engine = new groovy.text.SimpleTemplateEngine()
def subs = ['VARIABLE': 'REPLACED']
def newconfig = walk(config) { v ->
switch (v) {
case String:
return engine.createTemplate(v).make(subs)
default:
return v
}
}
这依赖于Groovy的智能switch
语句。它不是可扩展的,您不能只是插入自己的类型处理程序,但是它是如此简单,您不需要。默认情况下,它会进行混合复制,创建List
和Map
的新实例,但保留对原始标量或不匹配类型的引用。也可以按照以下身份转换示例进行深复制:
// Identity transform, shallow copy scalars
assert (config == (walk(config) { v -> v.clone() }))
// Identity transform, deep copy scalars where possible
assert (config == (walk(config) {
v ->
try {
return v.clone()
} catch (java.lang.CloneNotSupportedException ex) {
return v
}
}))
有什么想法吗?更好的方法?