Groovy/Java-JSON-通过变量路径更新JSON

Groovy/Java-JSON-通过变量路径更新JSON,java,json,groovy,soapui,Java,Json,Groovy,Soapui,有人知道如何在groovy中使用可变路径有效地设置json吗 上下文:我正在使用soapui,一种测试工具。有些测试是数据驱动的候选测试。我有很多变量。为了使某些东西在类似的情况下可以轻松实现,我想要一个Groovy脚本,它使我能够设置变量 我会将变量命名为“parent.subParent.child” 我发现: 我确实找到了其他东西,但没有把它们全部记录下来 我发现最直接的事情是评估。通过评估,可以获得值,但不能设置值 Eval.x(jsonbuilder, 'x.content.'

有人知道如何在groovy中使用可变路径有效地设置json吗

上下文:我正在使用soapui,一种测试工具。有些测试是数据驱动的候选测试。我有很多变量。为了使某些东西在类似的情况下可以轻松实现,我想要一个Groovy脚本,它使我能够设置变量

我会将变量命名为“parent.subParent.child”

我发现:

我确实找到了其他东西,但没有把它们全部记录下来

我发现最直接的事情是评估。通过评估,可以获得值,但不能设置值

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的基本JSON assign函数如下:
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好得多。