在 groovy 中动态执行代码
Posted
技术标签:
【中文标题】在 groovy 中动态执行代码【英文标题】:executing code dynamically in groovy 【发布时间】:2014-11-21 13:07:58 【问题描述】:我正在尝试在 groovy 中动态运行代码。我有someNode[0]
,这是变量var1
中的值
然后我像这样添加双引号
var2 = "\""+var1+"\""
然后我尝试运行它
request.abc."$var2"=Value
我看到here 可以在属性和方法上执行此类操作。但是上面的代码不起作用。给我错误
An error occurred [Cannot set property '"someNode[0]"' on null object], see error log for details
感谢任何帮助。谢谢。
编辑 这是我的请求的sn-p
"app":
"bundle":"531323947",
"cat":[
"IAB1",
"IAB9",
"IAB9-30",
"entertainment",
"games"
],
"id":"agltb3B1Yi1pbmNyDAsSA0FwcBitsL4UDA",
.
.
我要操作的字段是cat[0]
,即IAB1
(我只是在上面写的代码中使用了abc
和someNode[0]
,但实际上它们是app
和cat[0]
)
另外,在运行上述代码之前,我使用jsonslurper
解析了请求
感谢您的帮助
【问题讨论】:
怎么样 var2 = var1 request.abc."$var2"=Value @vahid 感谢您的回复。我试图跑var2 = var1
request.abc."$var2"=Value
,但它给了我同样的错误An error occurred [Cannot set property 'someNode[0]' on null object], see error log for details
通常 [0] 告诉 groovy 返回任何数组的第一个元素 - 它可能与此有关 - 有没有办法在你设置好值后删除它并添加它?
你能告诉我们你的要求吗? @vahid 是对的,虽然您可以通过字符串访问,但对于数组来说可能并不容易。您上面的代码可能已经失败,因为“请求”中没有“abc”。
@cfrick 我编辑了问题以显示请求。谢谢
【参考方案1】:
一种方法是通过Eval
def request =[
"app":[
"bundle":"531323947",
"cat":[
"IAB1",
"IAB9",
"IAB9-30",
"entertainment",
"games"
],
]
]
assert request.app.cat[0]=='IAB1'
def var = 'request.app.cat[0]'
Eval.me('request', request, "$var = 'new value'")
assert request.app.cat[0]=='new value'
【讨论】:
您应该非常小心地为Eval
提供用户内容!如果这是通过一些带有用户内容的网络界面提供的,我宁愿使用解析器。
我尝试了上述解决方案,但收到此错误 An error occurred [startup failed:Script1.groovy: 1:[parsed_MessageBody.app.cat[0]] is a constant expression, but it should be a variable expression at line: 1 column: 33. File: Script1.groovy @ line 1, column 33. 'parsed_MessageBody.app.cat[0]' = 'Value'^1 error], see error log for details
。不知道发生了什么。有什么想法吗?
@user1207289 'parsed_MessageBody.app.cat[0]' = 'Value'
看起来不对。它应该是parsed_MessageBody.app.cat[0] = 'Value'
(第一个字符串上没有引号)
感谢您的指出,我会尝试更改并发布结果。
现在工作正常。非常感谢,尽管我仍然需要找出 Eval.me('request', request, "$var = 'new value'")
在做什么。我知道eval
,但要了解您在 eval 中传递的第一个参数。第二和第三我有点理解。【参考方案2】:
您正在访问/更新地图和列表中的值。 request.app
节点将是一个地图,request.app.cat
节点将是一个列表。可以通过多种不同的方式获取和设置地图中的值:
-
直接使用
put
& get
方法。
使用括号[]
。
使用缺少的属性作为映射键(即您使用它的方式)。
对于您想要实现的目标,即从变量键访问值,使用方法 1 或 2 比方法 3 更容易,而方法 3 在 GString
中带有变量。
使用括号的示例:
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
def request = new JsonSlurper().parseText '''
"app":
"bundle":"531323947",
"cat":[
"IAB1",
"IAB9",
"IAB9-30",
"entertainment",
"games"
],
"id":"agltb3B1Yi1pbmNyDAsSA0FwcBitsL4UDA"
'''
def level0 = 'app'
def level1 = 'cat'
def node = request[level0][level1]
assert request instanceof Map
assert node instanceof List
assert node[0] == 'IAB1'
node[0] = 'new value'
assert node[0] == 'new value'
println new JsonBuilder(request).toPrettyString()
输出:
"app":
"cat": [
"new value",
"IAB9",
"IAB9-30",
"entertainment",
"games"
],
"id": "agltb3B1Yi1pbmNyDAsSA0FwcBitsL4UDA",
"bundle": "531323947"
【讨论】:
在我的情况下,我实现这一点的唯一问题是cat[0]
在一个变量中。在我看来,再次解析 cat[0]
的开销很大。我不能像 def level1 = 'cat'
和 node[0] = 'new value'
这样的硬编码。但在我看来,对于任何其他情况来说,这都是一个好方法。我会接受以下答案,因为它非常适合我的代码。我会提高你的答案,因为我从中吸取了教训。再次感谢您的意见。以上是关于在 groovy 中动态执行代码的主要内容,如果未能解决你的问题,请参考以下文章
GroovyMOP 元对象协议与元编程 ( 使用 Groovy 元编程进行函数拦截 | 动态拦截函数 | 动态获取 MetaClass 中的方法 | evaluate 方法执行Groovy脚本 )
GroovyGroovy 脚本调用 ( Groovy 类中调用 Groovy 脚本 | 创建 GroovyShell 对象并执行 Groovy 脚本 | 完整代码示例 )