string - property - hashmap add groovy
Groovy: ¿no hay un stringToMap fuera de la caja? (4)
Creo que estás buscando una combinación de ConfigObject y ConfigSlurper. Algo como esto haría el truco.
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}
}
Como desarrollador de TCL que comienza con Groovy, estoy un poco sorprendido por la lista y el soporte de mapas en Groovy. Tal vez me esté perdiendo algo aquí.
Estoy acostumbrado a convertir entre cadenas, listas y matrices / mapas en tcl sobre la marcha. En tcl, algo como
"[''a'':2,''b'':4]".each {key, value -> println key + " " + value}
sería posible, donde, como en groovy, cada comando pasa a través de cada carácter de la cadena.
Esto sería un gran problema porque podría usar fácilmente algo como el comando split o tokenize, pero como una lista o mapa serializado no es solo "a: 2, b: 4", es un poco más difícil de analizar.
Parece que los desarrolladores de griffon usan una biblioteca stringToMap ( http://code.google.com/p/stringtomap/ ) pero el ejemplo tampoco puede hacer frente a los mapas serializados.
Entonces mi pregunta es ahora: ¿cuál es la mejor manera de analizar un mapa o una lista en groovy?
Saludos, Ralf
PD: es una pregunta genial, pero la he etiquetado con griales, porque necesito esta funcionalidad para griales donde me gustaría pasar los mapas a través de la URL
Actualización: esta es todavía una pregunta abierta para mí ... así que aquí hay algunas actualizaciones para aquellos que tienen el mismo problema:
- cuando convierte un Mapa en una Cadena, un
.toString()
resultará en algo que no se puede volver a convertir en un mapa en todos los casos, pero un.inspect()
le dará una Cadena que puede ser evaluada de nuevo a un ¡mapa! - en Grails, hay un
.encodeAsJSON()
yJSON.parse(String)
; ambos funcionan bien, pero aún no he comprobado qué hará el analizador con las funciones JSON (posible problema de seguridad)
Es posible que desee probar algunos de sus escenarios utilizando la evaluación , podría hacer lo que está buscando.
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"
No exactamente groovy nativo, pero útil para serializar a 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)
con meta-programación:
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
desafortunadamente, no es posible anular el método toString () ...
Si no quieres usar evaluar (), hazlo en su lugar:
def stringMap = "[''a'':2,''b'':4]"
stringMap = stringMap.replaceAll(''//[|//]'','''')
def newMap = [:]
stringMap.tokenize('','').each {
kvTuple = it.tokenize('':'')
newMap[kvTuple[0]] = kvTuple[1]
}
println newMap