groovyから始めるtcl開発者として、私は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でマップまたはリストを解析するための最良の方法は何ですか?
乾杯、ラルフ
PS:かっこいい質問ですが、URLを介してマップを渡したいgrailsにこの機能が必要なため、grailsでタグ付けしました
更新:これはまだ私にとって未解決の質問です...したがって、同じ問題を抱えている人のためのいくつかの更新があります:
.toString()
はすべての場合にマップに戻すことができないものになりますが、.inspect()
は文字列を提供します。マップに戻って評価することができます!.encodeAsJSON()
とJSON.parse(String)
があります-どちらもうまく機能しますが、パーサーが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)
メタプログラミングあり:
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()メソッドをオーバーライドすることはできません。
evaluateを使用して、いくつかのシナリオを試してみることをお勧めします。探していることを実行できます。
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}
}
私はこの助けを願っています:
foo= "['a':2,'b':4]"
Map mapResult=[:]
mapResult += foo.replaceAll('\\[|\\]', '').split(',').collectEntries { entry ->
def pair = entry.split(':')
[(pair.first().trim()): pair.last().trim()]
}
Evaluation()を使用したくない場合は、代わりに次のようにしてください。
def stringMap = "['a':2,'b':4]"
stringMap = stringMap.replaceAll('\\[|\\]','')
def newMap = [:]
stringMap.tokenize(',').each {
kvTuple = it.tokenize(':')
newMap[kvTuple[0]] = kvTuple[1]
}
println newMap