groovy - 如何在 Groovy 中访问循环外的变量
问题描述
初学者警告!我有一个简单的 Groovy 脚本,旨在将参数列表分解为键值对,存储在关联数组(HashMap?)中。该代码在拆分参数之前工作正常,但是当它尝试将结果放回数组时,它会引发异常,说明它无法访问空元素。我想这样做的原因是它无法访问在循环外声明的变量。
这是脚本:
def input = "https://weyland-yutani.corp/engineering/bio?param1=1¶m2=2"
def params = [:] // wanna store key-value pairs here
if (input.split('\\?').size() >= 2) {
def p = input.split('\\?').last() // get the param string
p.split('\\&').each { // cut the string into an argument list
def keyval = it.split('=') // cut the argument into a key-value pair
println keyval // <-- prints "[param1, 1]", looks okay
params[keyval[0]].put(keyval[1]) // ERROR: "Cannot invoke method put() on null object"
//params[keyval[0]].add(keyval[1]) // ERROR, same sh**
}
}
错误信息:
Caught: java.lang.NullPointerException: Cannot invoke method put() on null object
java.lang.NullPointerException: Cannot invoke method put() on null object
at jdoodle$_run_closure1.doCall(jdoodle.groovy:10)
[...]
正如本文所述,您声明变量的方式会影响其范围,但我的尝试都没有成功。你能给我一个建议,我错过了什么吗?
解决方案
以下代码:
def input = "https://weyland-yutani.corp/engineering/bio?param1=1¶m2=2"
def params = input.tokenize('?').last().tokenize('&').collectEntries { keyval ->
keyval.tokenize('=')
}
println params.getClass()
println params
演示了这样做的一种方法。运行时,将打印:
─➤ groovy solution.groovy
class java.util.LinkedHashMap
[param1:1, param2:2]
─➤
作为替代方案,如果您可以使用外部库,则可以使用 url 解析类。这个来自 HttpBuilder 的例子(在这一点上有点过时了,可能还有其他的):
@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.2')
import groovyx.net.http.URIBuilder
def input = "https://weyland-yutani.corp/engineering/bio?param1=1¶m2=2"
def uri = new URIBuilder(input)
println uri.query.getClass()
println uri.query
它在运行时打印:
─➤ groovy solution2.groovy
class java.util.HashMap
[param1:1, param2:2]
─➤
再举一个例子,这次使用 google http 客户端库类GenericUrl
:
@Grab('com.google.http-client:google-http-client:1.39.1')
import com.google.api.client.http.GenericUrl
def input = "https://weyland-yutani.corp/engineering/bio?param1=1¶m2=2"
def url = new GenericUrl(input)
println (url instanceof Map)
url.each { k, v ->
println "$k -> $v"
}
println "value of param1: ${url.param1}"
其中,执行时打印:
─➤ groovy solution3.groovy
true
param1 -> [1]
param2 -> [2]
value of param1: [1]
─➤
应该指出的是,谷歌在这里做了正确的事情。当询问参数的值时,答案应该是一个列表。这是因为您可以说?a=1&a=2&a=3
,根据我的理解,不应将其解释为替换 的值a
,而应将其解释为值a
的列表1, 2, 3
。
因此,当您向谷歌图书馆询问参数的值时,您会得到一个列表,在这种情况下恰好是一个参数长。
推荐阅读
- mongodb - MongoDB 未连接到 EC2 服务器
- android-studio - Android Studio 3.5.3 显示设计视图为空但构建成功
- ios - 是否可以在 SwiftUI 中的某个路径上为视图设置动画
- javascript - 如何将 mySQL JSON 列转换为 javascript 数组?
- php - 如何使用 Ajax-Php 处理多个表单
- here-api - 这里 Map Javascript SDK 在手机的 Angular App 中运行,但性能太差了。如何提高手机设备(iPhone 6)的性能?
- sql - 提高 Spark SQL 中处理数十亿行数据的性能
- r - imap_dfr 3 个带有嵌套地图的列表的函数?
- c - C结构的内存布局
- php - 谷歌云打印停止工作(以前工作正常)