2010-02-06 27 views
19

Bir tcl geliştirici olarak groovy ile başlayan, ben liste ve harita desteği hakkında groovy biraz şaşırıyorum. Belki burada bir şey özlüyorum.Groovy: kutunun dışında bir stringToMap yok mu?

Ben tcl dizeleri, listeler ve diziler/haritalar arasında dönüştürmek için kullanıyorum. tcl mümkün olacağını

"['a':2,'b':4]".each {key, value -> println key + " " + value} 

gibi bir şey, nerede harika olduğu gibi, dizenin her karakter ile her komut adımları.

Bu bir sorun olabilir, split veya tokenize komutu gibi bir şeyi kolayca kullanabilirdim, ancak seri hale getirilmiş bir liste veya harita yalnızca "a: 2, b: 4" değil, birazcık ayrıştırmak daha zor.

Griffon geliştiricilerinin bir stringToMap kitaplığı kullandığı anlaşılıyor (http://code.google.com/p/stringtomap/) ancak örnek, seri hale getirilmiş haritalarla da baş edemiyor.

Bu yüzden sorum şu: Bir haritayı veya listeyi mükemmel bir şekilde ayrıştırmanın en iyi yolu nedir?

Alkış, Ralf

PS: Bu gelenekselleşmiş bir soru, ama ben URL üzerinden haritalar geçmek istiyorum grails için bu işlevi gerektiğinden, grails ile etiketlediniz

Güncelleme: bir Dizesi'ne bir harita açtığınızda

  • , bir .toString() yeniden olacaktır: Bu işte aynı sorun var olanlar için bazı güncelleştirmeler vardır ... hala benim için açık bir sorudur Her durumda bir haritaya geri döndürülemeyen bir şeye sığdırın, ancak bir .inspect() size bir haritayı değerlendirebileceğiniz bir String verecektir! Grails
  • , bir .encodeAsJSON() ve JSON.parse(String) var - iki büyük çalışır, ancak ben ayrıştırıcı JSON fonksiyonları (olası güvenlik sorunu)
+3

Eğer grails kullanıyorsanız ve bir harita istiyorsanız, bir JSON mesajını POST'ye bakmak istiyorum.İstemci tarafında daha kolay bir şekilde üretilmesi daha kolay ve JSON'u değerlendirmek için bir şeyler inşa edildi. –

+0

thanx. json gerçekten çok iyi bir alternatif olabilir! – rdmueller

+1

Haritaları Grails'deki URL'den geçirme, URL eşlemeleri için bir iş gibi ses çıkarır. Grails kullanım kılavuzunun Gömülü Değişkenler bölümüne bakın (bölüm 6.4.2). İstediğiniz haritayı iletmek için özel bir URL yapısı tanımlayabilirsiniz, örneğin, http://myapp.com/controller/action/key1/value1/key2/value2 Çok boyutlu haritalar için çok iyi çalışmaz ya da devasa veri yapıları, ama ben yine de bunların URL'lerle aktarılmaması gerektiğini iddia ediyorum. –

cevap

8

: Bunun yerine ne() değerlendirmek kullanmak istemiyorsanız

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" 
+1

Sanırım bu, temiz bir çözümdür ... biraz meta programlama ile Bu işlevsellik String sınıfına kolayca eklenebilir ... – rdmueller

+0

... ve Harita sınıfı ... – rdmueller

3

ben aradığınız düşünüyorum ne yapacak henüz kullanıma değil ConfigObject ve ConfigSlurper'ın bir kombinasyonu. Böyle bir şey hile yapardı.

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} 
} 
+0

thanx, slurper hakkında bilmek iyi! – rdmueller

21

Sen, o aradığınızı yapabilir değerlendirmek kullanarak senaryolar birkaç denemek isteyebilirsiniz.

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) 

meta ile: Tam olarak harika yerli ama JSON seri hale yararlı değil

def stringMap = "['a':2,'b':4]" 
stringMap = stringMap.replaceAll('\\[|\\]','') 
def newMap = [:] 
stringMap.tokenize(',').each { 
kvTuple = it.tokenize(':') 
newMap[kvTuple[0]] = kvTuple[1] 
} 
println newMap 
+0

thanx. Sanırım bu aradığım şeye yakın! – rdmueller

+0

vay. Sadece çözümün büyük bir güvenlik riski olduğunu fark ettim! Veriler URL'den geçirilirse ve yalnızca bir değerlendirme() yaparsak, her şey olabilir! Bu yüzden JSON çözümü daha iyi bir yol olacaktır ... – rdmueller

+3

GroovyShell'in üstünde basit bir yardımcı olan 'Eval' sınıfını kullanabilirsiniz:' def map = Eval.me ("['a': 2, 'b': 4] ")' –

1

-programlama:

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 

unfortun aceleyle, toString() yöntemini geçersiz kılmak mümkün değildir ...

+0

Bu sadece Dizelerle çalışacağından oldukça sınırlıdır. Örneğin, örneğinizde, newMap'e yerleştirilen değerler, 2 ve 4 sayıları değil, "2" ve "4" dizeleri olacaktır. –