string Groovy:没有现成的 stringToMap 吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2212606/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Groovy: isn't there a stringToMap out of the box?
提问by rdmueller
as a tcl developer starting with groovy, I am a little bit surprised about the list and map support in groovy. Maybe I am missing something here.
作为从 groovy 开始的 tcl 开发人员,我对 groovy 中的列表和地图支持感到有些惊讶。也许我在这里遗漏了一些东西。
I am used to convert between strings, lists and arrays/maps in tcl on the fly. In tcl, something like
我习惯于在 tcl 中动态地在字符串、列表和数组/映射之间进行转换。在 tcl 中,类似
"['a':2,'b':4]".each {key, value -> println key + " " + value}
would be possible, where as in groovy, the each command steps through each character of the string.
是可能的,在 groovy 中, each 命令会遍历字符串的每个字符。
This would be much of a problem is I could easily use something like the split or tokenize command, but because a serialized list or map isn't just "a:2,b:4", it is a little bit harder to parse.
这将是一个很大的问题,因为我可以轻松地使用诸如 split 或 tokenize 命令之类的东西,但是因为序列化列表或映射不仅仅是“a:2,b:4”,所以解析起来有点困难。
It seems that griffon developers use a stringToMap library (http://code.google.com/p/stringtomap/) but the example can't cope with the serialized maps either.
似乎 griffon 开发人员使用 stringToMap 库(http://code.google.com/p/stringtomap/),但该示例也无法处理序列化映射。
So my question is now: what's the best way to parse a map or a list in groovy?
所以我现在的问题是:在 groovy 中解析地图或列表的最佳方法是什么?
Cheers, Ralf
干杯,拉尔夫
PS: it's a groovy question, but I've tagged it with grails, because I need this functionality for grails where I would like to pass maps through the URL
PS:这是一个很好的问题,但我已经用 grails 标记了它,因为我需要这个功能用于 grails,我想通过 URL 传递地图
Update:This is still an open question for me... so here are some updates for those who have the same problem:
更新:这对我来说仍然是一个悬而未决的问题......所以这里有一些更新给那些有同样问题的人:
- when you turn a Map into a String, a
.toString()
will result in something which can't be turned back into a map in all cases, but an.inspect()
will give you a String which can be evaluated back to a map! - in Grails, there is a
.encodeAsJSON()
andJSON.parse(String)
- both work great, but I haven't checked out yet what the parser will do with JSON functions (possible security problem)
- 当您将 Map 转换为 String 时, a
.toString()
将导致在所有情况下都无法将其转换回Map 的结果,但是 an.inspect()
会给您一个可以评估回 Map 的 String! - 在 Grails 中,有一个
.encodeAsJSON()
andJSON.parse(String)
- 两者都很好用,但我还没有检查解析器将如何处理 JSON 函数(可能存在安全问题)
采纳答案by Jonas Eicher
Not exactly native groovy, but useful for serializing to JSON:
不完全是原生的 groovy,但对于序列化为 JSON 很有用:
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
def map = ['a':2,'b':4 ]
def s = new JsonBuilder(map).toString()
println s
assert map == new JsonSlurper().parseText(s)
with meta-programming:
元编程:
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
Map.metaClass.toJson = { new JsonBuilder(delegate).toString() }
String.metaClass.toMap = { new JsonSlurper().parseText(delegate) }
def map = ['a':2,'b':4 ]
assert map.toJson() == '{"a":2,"b":4}'
assert map.toJson().toMap() == map
unfortunately, it's not possible to override the toString() method...
不幸的是,不可能覆盖 toString() 方法......
回答by John Wagenleitner
You might want to try a few of your scenarios using evaluate, it might do what you are looking for.
您可能想使用评估尝试一些场景,它可能会满足您的需求。
def stringMap = "['a':2,'b':4]"
def map = evaluate(stringMap)
assert map.a == 2
assert map.b == 4
def stringMapNested = "['foo':'bar', baz:['alpha':'beta']]"
def map2 = evaluate(stringMapNested)
assert map2.foo == "bar"
assert map2.baz.alpha == "beta"
回答by Grega Ke?pret
I think you are looking for a combination of ConfigObjectand ConfigSlurper. Something like this would do the trick.
我认为您正在寻找ConfigObject和 ConfigSlurper的组合。像这样的事情可以解决问题。
def foo = new ConfigObject()
foo.bar = [ 'a' : 2, 'b' : 4 ]
// we need to serialize it
new File( 'serialized.groovy' ).withWriter{ writer ->
foo.writeTo( writer )
}
def config = new ConfigSlurper().parse(new File('serialized.groovy').toURL())
// highest level structure is a map ["bar":...], that's why we need one loop more
config.each { _,v ->
v.each {key, value -> println key + " " + value}
}
回答by Noam Manos
If you don't want to use evaluate(), do instead:
如果您不想使用evaluate(),请改为:
def stringMap = "['a':2,'b':4]"
stringMap = stringMap.replaceAll('\[|\]','')
def newMap = [:]
stringMap.tokenize(',').each {
kvTuple = it.tokenize(':')
newMap[kvTuple[0]] = kvTuple[1]
}
println newMap
回答by Alireza
I hope this help:
我希望这会有所帮助:
foo= "['a':2,'b':4]"
Map mapResult=[:]
mapResult += foo.replaceAll('\[|\]', '').split(',').collectEntries { entry ->
def pair = entry.split(':')
[(pair.first().trim()): pair.last().trim()]
}