Groovy/Java-JSON-通过变量路径更新JSON
有人知道如何在groovy中使用可变路径有效地设置json吗 上下文:我正在使用soapui,一种测试工具。有些测试是数据驱动的候选测试。我有很多变量。为了使某些东西在类似的情况下可以轻松实现,我想要一个Groovy脚本,它使我能够设置变量 我会将变量命名为“parent.subParent.child” 我发现:Groovy/Java-JSON-通过变量路径更新JSON,java,json,groovy,soapui,Java,Json,Groovy,Soapui,有人知道如何在groovy中使用可变路径有效地设置json吗 上下文:我正在使用soapui,一种测试工具。有些测试是数据驱动的候选测试。我有很多变量。为了使某些东西在类似的情况下可以轻松实现,我想要一个Groovy脚本,它使我能够设置变量 我会将变量命名为“parent.subParent.child” 我发现: 我确实找到了其他东西,但没有把它们全部记录下来 我发现最直接的事情是评估。通过评估,可以获得值,但不能设置值 Eval.x(jsonbuilder, 'x.content.'
Eval.x(jsonbuilder, 'x.content.' + path) = 'newValue'
将返回一个错误。但正如我所说,以这种方式检索json中的值没有问题
我尝试的是:
我已经得到了一个实现,它只适用于一个级别。
我可以说:
jsonbuilder.content.parent.subParent[child] = 'newValue'
这将设置所请求实体的值
然后我尝试将其扩展到一个未定义的级别
//Assuming there is a jsonbuilder initialized
def jsonString = "{"parent":{"subParent":{"child":"oldValue"}}}"
def json = new JsonSlurper().parseText(jsonString)
def jsonbuilder = new JsonBuilder(json)
def path = 'parent.subParent.child'
def listPath = path.split("\\.")
def element = jsonbuilder.content
for(int i = 0; i < listPath.size(); i++) {
element = element[listPath[i]]
}
element = 'newValue'
assert jsonbuilder.toString() == "{"parent":{"subParent":{"child":"newValue"}}}"
//假设有一个已初始化的jsonbuilder
def jsonString=“{”parent:{”subParent:{”child:“oldValue”}}”
def json=new JsonSlurper().parseText(jsonString)
def jsonbuilder=新jsonbuilder(json)
def path='parent.subParent.child'
def listPath=path.split(“\\”)
def元素=jsonbuilder.content
对于(int i=0;i
问题:原始json中的值没有更新。可能是因为在将jsonbuilder变量分配给“element”并继续使用该实体之后,我就离开了它
这给我留下了两个问题:
- 如何获取原始json中的元素值
- 更一般:如何使用变量路径更新json
jsonbuilder.content.parent.subParent.child='newValue'
,这不是我想要的。我正在寻找一种方法,使整个事情充满活力。我不想建立一个简单的任务,它已经存在并且运行良好。我正在寻找建立一台机器,为我做分配,与变量名解析为路径。最好是在groovy.json.*环境中,但如果我必须使用外部库,那就这样吧。给你:
import groovy.json.JsonSlurper
import groovy.json.JsonBuilder
def jsonString = """{ "parent": {
"subParent": {
"child": "oldValue"
}
}
}"""
def json = new JsonSlurper().parseText(jsonString)
def jsonbuilder = new JsonBuilder(json)
//Assign the value for child with new value
jsonbuilder.content.parent.subParent.child = 'newValue'
println jsonbuilder.toPrettyString()
import com.jayway.jsonpath.Configuration
import com.jayway.jsonpath.JsonPath
import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider
Configuration configuration = Configuration.builder()
.jsonProvider(new JacksonJsonNodeJsonProvider())
.mappingProvider(new JacksonMappingProvider())
.build()
//You need to prepend $. before the path which becomes valid jsonpath
def path = '$.parent.subParent.child'
def originalJson = """{
"parent": {
"subParent": {
"child": "oldValue"
}
}
}"""
def updatedJson = JsonPath.using(configuration).parse(originalJson).set(path, 'newValue').json()
println(updatedJson.toString())
既然您愿意使用library,您可以在线试用 来自@kalle的学分
- 从下载zip文件
- 从上面的zip文件中提取库及其依赖项
- 将它们复制到SOAPUI_HOME/bin/ext目录下
- 重新启动SoapUI
import groovy.json.JsonSlurper
import groovy.json.JsonBuilder
def jsonString = """{ "parent": {
"subParent": {
"child": "oldValue"
}
}
}"""
def json = new JsonSlurper().parseText(jsonString)
def jsonbuilder = new JsonBuilder(json)
//Assign the value for child with new value
jsonbuilder.content.parent.subParent.child = 'newValue'
println jsonbuilder.toPrettyString()
import com.jayway.jsonpath.Configuration
import com.jayway.jsonpath.JsonPath
import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider
Configuration configuration = Configuration.builder()
.jsonProvider(new JacksonJsonNodeJsonProvider())
.mappingProvider(new JacksonMappingProvider())
.build()
//You need to prepend $. before the path which becomes valid jsonpath
def path = '$.parent.subParent.child'
def originalJson = """{
"parent": {
"subParent": {
"child": "oldValue"
}
}
}"""
def updatedJson = JsonPath.using(configuration).parse(originalJson).set(path, 'newValue').json()
println(updatedJson.toString())
我对Eval的具体实现视而不见。如果我从一开始就阅读文档,我的解决方案其实很简单 您可以在此处找到用于评估的文档: 我认为,与其尝试将一个值赋给一个已求值的方法/函数(这是不符合逻辑的),不如将所有内容都集成到已求值的表达式中。我发现,在求值函数中最多可以使用三个变量 我只需要两个。我需要jsonbuilder对象能够获取信息源。我需要得到要设置的值。路径本身可以在其存在时使用,因为它已经是计算所需的:字符串 守则:
import groovy.json.*
def jsonString = '{"parent":{"child":"oldValue"}}'
def newValue = 'newValue'
def stringPath = 'parent.child'
def json = new JsonSlurper().parseText(jsonString)
def jsonbuilder = new JsonBuilder(json)
Eval.xy(jsonbuilder, newValue, 'x.content.' + stringPath + '= y')
System.out.println(jsonbuilder.toString()=='{"parent":{"child":"newValue"}}')
System.out.println(jsonbuilder.content.parent.child == 'newValue')
通过使用Eval.xy(objectOne,objectTwo,StringExpression)
,我告诉您我正在传递一个字符串作为表达式进行计算,其中x表示objectOne,y表示objectTwo
可以在在线groovy脚本引擎中查看代码:
小免责声明:我无法想象在代码库中使用求值表达式,让外部世界随意操纵变量。如果使用此表达式,它将在我的SoapUI项目的上下文中得到很好的体现。@Matthiasdirickx,感谢您投票给我有用的答案。如果你认为这是最好的解决方案,考虑接受它作为答案。或者你在寻找不同的解决方案?但问题是如何让它充满活力。它并不总是三级的,而且名字也不预先知道。你举的例子就是我现在设置的。那么,我如何使路径变量?如问题正文所示,使用括号时可以使用变量。但这并没有考虑到不同的层次。至于你的问题,还有一些上下文。在SoapUI中,您可以定义变量。我想通过REST服务使用必填字段创建和扩展测试。有220个字段,因此有220个变量。我想我可以用变量的路径命名变量,而不是为每个变量创建一个赋值,以便能够通过excel工作表更新SoapUI中的REST请求消息。无论如何,我必须给它们下定义。然后我可以创建一个更短的脚本,它可以自动将变量分配到REST请求中的正确位置。它将有助于使用JSON POST消息体(我们有很多)对服务中的字段配置进行特别测试,而不必过多地钻研任务和技术规范/脚本。这将使它更容易为广大公众所接受。这只是为了添加一些上下文。也许有一种更有效的方法来解决这个问题,而我在这里选错了三个…:)@Matthiasdirickx,请看你问题的另一个答案。与excel相比,xlson非常简单,所以建议这样做。这比使用Groove好得多。