web-dev-qa-db-ja.com

Groovy:すぐに使えるstringToMapはありませんか?

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()は文字列を提供します。マップに戻って評価することができます!
  • grailsには、.encodeAsJSON()JSON.parse(String)があります-どちらもうまく機能しますが、パーサーがJSON関数で何をするかはまだチェックしていません(セキュリティ上の問題の可能性があります)
24
rdmueller

正確にはネイティブの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()メソッドをオーバーライドすることはできません。

13
Jonas Eicher

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"
25

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}
}
3
Grega Kešpret

私はこの助けを願っています:

    foo= "['a':2,'b':4]"
    Map mapResult=[:]
    mapResult += foo.replaceAll('\\[|\\]', '').split(',').collectEntries { entry ->
        def pair = entry.split(':')
        [(pair.first().trim()): pair.last().trim()]
       }
1
Alireza

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
1
Noam Manos