2010-02-06 2 views
19

как разработчик tcl, начиная с groovy, я немного удивлен тем, что список и поддержка карт в groovy. Может быть, я что-то упустил.Groovy: нет ли строки из списка?

Я использую для преобразования между строками, списками и массивами/картами в tcl на лету. В Tcl, что-то вроде

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

было бы возможно, где, как в заводных шагах каждой команды через каждый символ строки.

Это была бы большая проблема, я мог бы легко использовать что-то вроде команды split или tokenize, но поскольку сериализованный список или карта не просто «a: 2, b: 4», это немного сложнее разобрать.

Похоже, разработчики гриффона используют библиотеку stringToMap (http://code.google.com/p/stringtomap/), но этот пример также не может справиться с сериализованными картами.

Итак, мой вопрос: какой лучший способ разобрать карту или список в groovy?

Приветствие, Ralf

PS: это заводной вопрос, но я помечать его с Грааль, потому что мне нужна эта функциональность для Грааль, где я хотел бы передать карты через URL

Обновление: Это вопрос остается открытым для меня ... так вот некоторые обновления для тех, у кого есть такая же проблема:

  • при включении карты в строка, .toString() будет повторно sult в чем-то, что не может быть обращено обратно на карту во всех случаях, но .inspect() даст вам строку, которая может быть оценена обратно на карту!
  • в Grails, есть .encodeAsJSON() и JSON.parse(String) - и отлично работают, но я не проверил еще, что анализатор будет делать с JSON функций (возможно, проблема безопасности)
+3

Если вы используете grails и хотите получить карту, я бы посмотрел сообщение POSTing JSON.Вероятно, легче сгенерировать на стороне клиента, и для оценки JSON есть вещи, встроенные в grails. –

+0

thanx. json действительно может быть очень хорошей альтернативой! – rdmueller

+1

Передача карт через URL-адрес в Grails звучит как задание для сопоставлений URL-адресов. Ознакомьтесь с разделом Embedded Variables руководства пользователя Grails (раздел 6.4.2). Вы можете определить настраиваемую структуру URL для передачи любой желаемой карты, то есть http://myapp.com/controller/action/key1/value1/key2/value2 Это не будет работать слишком хорошо для многомерных карт , или огромные структуры данных, но я бы утверждать, что они не должны передаваться через URL-адреса в любом случае. –

ответ

8

Не совсем родной заводной, но полезный для сериализации 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 

unfortun возможно, переопределить метод toString() невозможно ...

+1

Я думаю, это чистое решение ... с небольшим количеством метапрограмм , эта функциональность может быть легко добавлена ​​в класс String ... – rdmueller

+0

... и класс карты ... – rdmueller

3

Я думаю, вы ищете комбинация 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} 
} 
+0

thanx, хорошо знать о slurper! – rdmueller

21

Вы можете попробовать некоторые из ваших сценариев с использованием оценки, он может делать то, что вы ищете.

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

thanx. Я думаю, это близко к тому, что я искал! – rdmueller

+0

ничего себе. просто заметил, что решение представляет собой большой риск для безопасности! Если данные передаются через URL-адрес, и мы просто делаем для него оценку(), все может случиться! Итак, я думаю, что решение JSON будет лучшим способом ... – rdmueller

+3

Вы можете использовать класс Eval, который является простым помощником поверх GroovyShell: 'def map = Eval.me (" ['a': 2, 'b': 4] ")' –

1

Если вы не хотите использовать оценку(), вместо того, чтобы сделать:

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

Это довольно ограниченный, поскольку он будет работать только с Строками. Например, в вашем примере значения, которые помещаются в newMap, будут строками «2» и «4», а не цифрами 2 и 4. –

 Смежные вопросы

  • Нет связанных вопросов^_^