我试图创建一个粗略的json输出器,它接收一个键值对列表并产生相应的json。这就是我所拥有的:
class keyValuePairs {
private String[][] contents
keyValuePairs(String[][] inputList) {
contents = inputList
}
public String json() {
String jsonString = '{\n'
String[] keyVals = contents collect {jsonPair it}
jsonString += keyVals.join(',\n') + '\n'
jsonString += '}'
return jsonString
}
String jsonPair(String[] keyVal) {
return ' "' + keyVal[0] + '": "' + keyVal[1] + '"'
}
}
我的keyValuesPairs接受一个字符串列表列表,这个编译很好,但我的内容收集{jsonPair it} 行失败了:
Caught: groovy.lang.MissingMethodException: No signature of method: auditconfigprototype.keyValuePairs.jsonPair() is applicable for argument types: (auditconfig
prototype.keyValuePairs) values: [auditconfigprototype.keyValuePairs@7fa98a66]
Possible solutions: jsonPair([Ljava.lang.String;), json()
我可以回到内容上的循环,但我想采用收集的功能方法。但是,似乎每次尝试(甚至是微不足道的!)都会在我的内容列表上执行收集失败。我将列表定义错了吗?我应该如何在字符串列表列表中使用收集?
答案 0 :(得分:2)
你得到的例外是由于这一行:
String[] keyVals = contents collect {jsonPair it}
乍一看,这似乎相当于:
String[] keyVals = contents.collect {jsonPair it}
但事实上,你得到的是:
String[] keyVals = contents(collect() {jsonPair it})
分配 keyVals 变量时, keyValuePairs 实例上正在调用 collect()方法;在这个上。
collect()然后遍历包含单个项目的List,即 keyValuePairs 的实例,并使用 keyValuePairs 实例调用闭包。 jsonPair()方法需要 String 数组,但会收到 keyValuePairs 。这就是抛出异常的原因:
groovy.lang.MissingMethodException: No signature of method: keyValuePairs.jsonPair() is applicable for argument types: (keyValuePairs) values: [keyValuePairs@63169fe0]
解决方案是简单地添加缺失的句点以使代码如下:
String[] keyVals = contents.collect {jsonPair it}
作为练习,这是实现解析器的另一种方法。
def a = [
['firstname', 'John'],
['lastname', 'Doe'],
['language', 'Groovy']
]
class KeyValuePairs {
def pairs
String json() {
new StringBuilder('{\n').with {
append(
pairs
.collect { String.format('"%s":"%s"', it[0], it[1]) }
.collect { "\t$it" }.join(',\n'))
append '\n}\n'
}.toString()
}
}
def parser = new KeyValuePairs(pairs: a)
parser.json()
此实现使用列表< 列表>而不是数组,因为Groovy对它们有很好的内置支持。
通过使用Groovy Beans,可以创建 KeyValuePairs 实例,而无需显式创建样板构造函数。
使用 StringBuilder 代替字符串连接。主要是因为我认为它使代码看起来更好。
由于格式化需要双引号,我使用 String.format()。这使格式化易于阅读。注意:通常我会使用GString。
由于格式化的应用非常简洁,我取消了 jsonPair()方法。
第一个 collect()会产生如下输出:
[
'"firstname":"John"',
'"lastname":"Doe"',
'"language":"Groovy"'
]
第二个 collect()在每对的双引号前添加一个TAB。最后, join()构建单个String对。
另一种改进代码的方法是替换
it[0], it[1]
与
it.key, it.value
这可以通过用这两个替换第一个 collect()来完成:
.collect { [['key', 'value'], it].transpose().collectEntries() }
.collect { String.format('"%s":"%s"', it.key, it.value) }
我希望这会有所帮助:)