Groovy: non c'è uno stringToMap fuori dalla scatola?
Domanda
come sviluppatore TCL inizia con groove, io sono un po 'sorpreso per il sostegno e la lista mappa in Groovy. Forse mi manca qualcosa qui.
Sono abituato per la conversione tra stringhe, liste e array / mappe in tcl al volo. In tcl, qualcosa come
"['a':2,'b':4]".each {key, value -> println key + " " + value}
sarebbe possibile, dove come in scanalato, le fasi di comando ciascuno attraverso ogni carattere della stringa.
Questo sarebbe un gran problema è ho potuto facilmente usare qualcosa come la scissione o il comando tokenize, ma perché una lista o una mappa serializzato non è solo "un: 2, B: 4", è un po 'più difficile per analizzare.
Sembra che gli sviluppatori di grifoni utilizzare una libreria stringToMap ( http://code.google.com/p / stringtomap / ), ma l'esempio non può far fronte con le mappe serializzati sia.
Quindi la mia domanda è ora: qual è il modo migliore per analizzare una mappa o un elenco in Groovy
Saluti, Ralf
PS: è una questione Groovy, ma ho etichettato con Grails, perché ho bisogno di questa funzionalità per graal in cui mi piacerebbe passare le mappe tramite l'URL
Aggiornamento: Questa è ancora una questione aperta per me ... quindi ecco alcuni aggiornamenti per coloro che hanno lo stesso problema:
- quando si accende una mappa in una stringa, un
.toString()
si tradurrà in qualcosa che non può essere trasformato di nuovo in una mappa in tutti i casi, ma un.inspect()
vi darà una stringa che può essere valutato di nuovo a una mappa! - in Grails, c'è un
.encodeAsJSON()
eJSON.parse(String)
- entrambi funzionano molto bene, ma non ho verificato ancora che cosa il parser che fare con le funzioni di JSON (possibile problema di sicurezza)
Soluzione
Non esattamente nativo Groovy, ma utile per la serializzazione 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-programmazione:
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
purtroppo, non è possibile eseguire l'override del metodo toString () ...
Altri suggerimenti
Si potrebbe desiderare di provare alcuni dei vostri scenari utilizzando valutare , si potrebbe fare quello che stai cercando.
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"
Credo che siete alla ricerca di una combinazione di ConfigObject ConfigSlurper. Qualcosa di simile a questo sarebbe fare il trucco.
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}
}
Se non si desidera utilizzare la valutazione (), fare, invece:
def stringMap = "['a':2,'b':4]"
stringMap = stringMap.replaceAll('\\[|\\]','')
def newMap = [:]
stringMap.tokenize(',').each {
kvTuple = it.tokenize(':')
newMap[kvTuple[0]] = kvTuple[1]
}
println newMap