groovy GPath中的JSONPath联合“[,]”等效项

ctzwtxfj  于 2022-11-01  发布在  其他
关注(0)|答案(2)|浏览(137)

考虑给定的JSON

{
  "data": {
    "array": [
      {
        "foo": {"a": "1 foo a", "b": "2 foo b", "c": 512},
        "bar": {"a": "3 bar a", "b": "4 bar b"},
        "baz": {"a": "5 baz a", "b": "6 baz b", "d": 75},
        "other": {"a": 2, "x": 13, "y": 44},
      },
      {
        "foo": {"a": "7 foo a", "b": "8 foo b"},
        "bar": {"a": "9 bar a", "b": "10 bar b"},
        "baz": {"a": "11 baz a", "b": "12 baz b"},
        "other": {"a": 2, "x": 13, "y": 44, "z": 132},
      }
    ]
  }
}

使用简单的JSONPath,我可以按相应的顺序列出foobarbaz中的所有ab
第一个
有没有什么方法可以使用GroovyGPath来实现这一点呢?我提出的唯一可行的解决方案是:

def json = new JsonSlurper().parseText(jsonText)

json.data.array.foo.a
+ json.data.array.foo.b
+ json.data.array.bar.a
+ json.data.array.bar.b
+ json.data.array.baz.a
+ json.data.array.baz.b

但结果仍与JSONPath不同(按顺序)

[1 foo a, 7 foo a,
 2 foo b, 8 foo b,
 3 bar a, 9 bar a,
 4 bar b, 10 bar b,
 5 baz a, 11 baz a, 
 6 baz b, 12 baz b]

附:
我正在使用GPath进行我的Rest-Assured测试,所以如果有替代方法可以在Rest-Assured测试中获得相同的结果,我会很高兴看到它。
P.P.S
其实我找到了另一个解决办法

json.data.array
    *.subMap(["foo", "bar", "baz"])*.values().flatten()
    *.subMap(["a", "b"])*.values().flatten()

它产生的结果与JSONPath相同

[1 foo a, 2 foo b,
 3 bar a, 4 bar b,
 5 baz a, 6 baz b,
 7 foo a, 8 foo b,
 9 bar a, 10 bar b,
 11 baz a, 12 baz b]

但是它仍然不是JSONPath中联合操作的替代方案。

$.data.array[*][foo,bar,?(@.a == '11 baz a')][a,b]

该解决方案的GPath替代方案与上面的subMap解决方案完全不同。

yhxst69z

yhxst69z1#

下面是使用collectMany和collect方法来解决您的问题的纯gpath版本:
根据RomanMitasov的更新问题更新了答案:

def json = new JsonSlurper().parseText(text) //text is your json string
def result = json.data.array*.collectMany{k,v-> k in ["foo","bar","baz"]? v.collect{k1,v1-> k1 in ["a","b"]? v1:[]}:[]}.flatten()
println result //[1 foo a, 2 foo b, 3 bar a, 4 bar b, 5 baz a, 6 baz b, 7 foo a, 8 foo b, 9 bar a, 10 bar b, 11 baz a, 12 baz b]

原始答案:

def json = new JsonSlurper().parseText(text) //text is your json string
def result = json.data.array*.collectMany{k,v->v.collect{it.value}}.flatten()
println result //[1 foo a, 2 foo b, 3 bar a, 4 bar b, 5 baz a, 6 baz b, 7 foo a, 8 foo b, 9 bar a, 10 bar b, 11 baz a, 12 baz b]
vlf7wbxs

vlf7wbxs2#

多亏了@Xiao,我想出了一个最接近JsonPath的解决方案:

def json = new JsonSlurper().parseText(input) //text is your json string

def result = json.data.array
        .collectMany { [it.foo, it.bar, it.baz] }
        .collectMany { [it.a, it.b] }

println result // [1 foo a, 2 foo b, 3 bar a, 4 bar b, 5 baz a, 6 baz b, 7 foo a, 8 foo b, 9 bar a, 10 bar b, 11 baz a, 12 baz b]

然而,如果我想替代

$.data.array[*][foo,bar,?(@.a == '11 baz a')][a,b]

结果是更脏:

def result = json.data.array
        .collectMany {
            [it.foo, it.bar] + (it.baz.a == '11 baz a' ? it.baz : [])
        }
        .collectMany { [it.a, it.b] }

我认为,如果我们省略了过滤器的用法,collectMany可以被认为是[,]的等价物。
P.S.欢迎您的过滤联合版本

相关问题