Groovy: разве нет stringToMap из коробки?
как разработчик tcl, начиная с groovy, я немного удивлен поддержкой списка и карты в groovy. Может быть, я что-то упускаю.
Я используется для преобразования между строками, списками и массивами / картами в tcl на лету. В tcl что-то вроде
"['a':2,'b':4]".each {key, value -> println key + " " + value}
было бы возможно, где, как в groovy, каждая команда проходит через каждый символ строки.
Это было бы большой проблемой, я мог бы легко использовать что-то вроде команда split или tokenize, но поскольку сериализованный список или карта-это не просто "a:2,b: 4", ее немного сложнее разобрать.
похоже, что разработчики griffon используют библиотеку stringToMap (http://code.google.com/p/stringtomap/) но пример также не может справиться с сериализованными картами.
Итак, мой вопрос: каков наилучший способ проанализировать карту или список в groovy?
Ура, Ральф!--6-->
PS: Это классный вопрос, но у меня есть пометил его граалями, потому что мне нужна эта функциональность для граалей, где я хотел бы передать карты через URL
обновление: это все еще открытый вопрос для меня... так вот некоторые обновления для тех, кто имеет ту же проблему:
- когда вы превращаете карту в строку, a
.toString()
выльется в то, что не может быть превращен обратно в карту во всех случаях, но.inspect()
даст вам строку, которая может быть оценена обратно карта! - в Grails, есть
.encodeAsJSON()
иJSON.parse(String)
- оба отлично работают, но я еще не проверил, что парсер будет делать с функциями JSON (возможная проблема безопасности)
4 ответов
не совсем родной 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)
С мета-программирования:
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
к сожалению, невозможно переопределить метод toString ()...
вы можете попробовать несколько сценариев с помощью оценить он может делать то, что вы ищете.
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"
Я думаю, что вы ищете комбинацию 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}
}
Если вы не хотите использовать 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