Groovy/Java - JSON - 通过变量路径更新JSON
Groovy/Java - JSON - Update JSON through variable path
有人知道如何使用可变路径有效地在 groovy 中设置 json 吗?
上下文:我正在使用测试工具soapui。一些测试是数据驱动的候选者。我有很多变数。为了使在类似情况下易于实施的可持续发展,我想要一个 Groovy 脚本,使我能够设置变量。
我会将变量命名为 'parent.subParent.child'。
我发现了什么:
Referencing groovy variable as part of JSON path
其他的我也找到了,但是没有全部记录下来
我发现最直接的是评估。通过评估,可以获得值,但不能设置值。
Eval.x(jsonbuilder, 'x.content.' + path) = 'newValue'
会return一个错误。但是就像我说的,以这种方式检索 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"}}}"
问题:原始 json 中的值未更新。可能是因为我将 jsonbuilder 变量分配给 'element' 并继续使用该实体。
这给我留下了两个问题:
- 如何获取原始json中的元素值?
- 更一般:如何使用可变路径更新 json?
使用 jsonbuilder 的基本 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()
您可以在线试一下Demo
既然您愿意使用图书馆,那么json-path就可以了。
感谢@kalle 来自here
- 从 here
下载 zip 文件
- 从上面的 zip
中提取库及其依赖项
- 将它们复制到 SOAPUI_HOME/bin/ext 目录下
- 重新启动 SoapUI
给你:
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 的具体实现视而不见。如果我从一开始就阅读文档,我的解决方案实际上很简单。
您可以在此处找到 Eval 的文档:http://docs.groovy-lang.org/2.4.7/html/api/groovy/util/Eval.html
与其尝试为已求值的 method/function 赋值,我现在认为这不合逻辑,而是需要将所有内容集成到已求值的表达式中。根据我的发现,您最多可以在 Eval 函数中使用三个变量。
我只需要两个。我需要 jsonbuilder 对象才能获取信息源。我需要获取要设置的值。路径本身可以按其存在的方式使用,因为它已经是评估所需要的:一个 String.
代码:
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 脚本引擎中查看代码:https://groovyconsole.appspot.com/edit/5202721384693760
小免责声明:我无法想象在代码库中使用计算表达式,让变量被外界随机操纵。这个表达式,如果使用的话,将很舒服地放在我的 SoapUI 项目的上下文中。
有人知道如何使用可变路径有效地在 groovy 中设置 json 吗?
上下文:我正在使用测试工具soapui。一些测试是数据驱动的候选者。我有很多变数。为了使在类似情况下易于实施的可持续发展,我想要一个 Groovy 脚本,使我能够设置变量。
我会将变量命名为 'parent.subParent.child'。
我发现了什么:
Referencing groovy variable as part of JSON path
其他的我也找到了,但是没有全部记录下来
我发现最直接的是评估。通过评估,可以获得值,但不能设置值。
Eval.x(jsonbuilder, 'x.content.' + path) = 'newValue'
会return一个错误。但是就像我说的,以这种方式检索 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"}}}"
问题:原始 json 中的值未更新。可能是因为我将 jsonbuilder 变量分配给 'element' 并继续使用该实体。
这给我留下了两个问题:
- 如何获取原始json中的元素值?
- 更一般:如何使用可变路径更新 json?
使用 jsonbuilder 的基本 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()
您可以在线试一下Demo
既然您愿意使用图书馆,那么json-path就可以了。
感谢@kalle 来自here
- 从 here 下载 zip 文件
- 从上面的 zip 中提取库及其依赖项
- 将它们复制到 SOAPUI_HOME/bin/ext 目录下
- 重新启动 SoapUI
给你:
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 的具体实现视而不见。如果我从一开始就阅读文档,我的解决方案实际上很简单。
您可以在此处找到 Eval 的文档:http://docs.groovy-lang.org/2.4.7/html/api/groovy/util/Eval.html
与其尝试为已求值的 method/function 赋值,我现在认为这不合逻辑,而是需要将所有内容集成到已求值的表达式中。根据我的发现,您最多可以在 Eval 函数中使用三个变量。
我只需要两个。我需要 jsonbuilder 对象才能获取信息源。我需要获取要设置的值。路径本身可以按其存在的方式使用,因为它已经是评估所需要的:一个 String.
代码:
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 脚本引擎中查看代码:https://groovyconsole.appspot.com/edit/5202721384693760
小免责声明:我无法想象在代码库中使用计算表达式,让变量被外界随机操纵。这个表达式,如果使用的话,将很舒服地放在我的 SoapUI 项目的上下文中。