如何在Java中使用JSONPath搜索数组?

时间:2015-12-24 11:17:23

标签: json jsonpath

我想使用json-path-assert为Web服务编写单元测试。鉴于此JSON:

[ 
  ["Some short name","Some parent","Some name"],
  ["Some short name 2","Some parent 2","Some name 2"] 
]

我想检查"有些名字2"的父母。是"有些父母2"。我不能改变JSON的结构,因为它是由第三方库决定的。

这是我提出的JSONPath表达式:

$..[?(@[2] == 'Some name 2')][1]

此表达式工作正常,并在this JSON tool中返回预期结果('某些父级2')。但是,当使用JSONPath库在Java中使用它时,我得到一个空结果而不是正确的值:

import com.jayway.jsonpath.JsonPath;
import org.junit.Test;

public class TestJSONPath
{
  @Test
  public void testJsonPath() {
     String json = "[[\"Some short name\",\"Some parent\",\"Some name\"]," +
       "[\"Some short name 2\",\"Some parent 2\",\"Some name 2\"]]";

     System.out.println(JsonPath.read(json, "$[1][1]"));    // OK, returns 'Some parent 2'
     System.out.println(JsonPath.read(json, "$..[?(@[2] == 'Some name 2')][1]")); // Not OK, returns an empty list
 }
}

这是我的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>test</groupId>
  <artifactId>test</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.jayway.jsonpath</groupId>
      <artifactId>json-path</artifactId>
      <version>2.1.0</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.jayway.jsonpath</groupId>
      <artifactId>json-path-assert</artifactId>
      <version>2.1.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

你能帮我解决一下如何克服这个问题吗?

1 个答案:

答案 0 :(得分:3)

这可行: $[?(@[2] == 'Some name 2')][1]

<强>背景

如果您尝试"original" JSONPath implementation编写的Stefan Goessner,则以下表达式将返回预期的数组:

$..[?(@[2] == 'Some name 2')](索引2处的值为&#39;某些名称为2&#39;的后代)

===> ["Some parent 2"]

有趣的是......用jayway,Goessners-JSON-lib或jsonquerytool尝试这些表达式:

"$..*" //list of all descendants (both child-arrays + elements in arrays)
"$.*" //list of all direct children (both child arrays)
"$" //actual element (the array itself)

Stefan Goessner的JavaScript库与&#34; jayway&#34;相同。实现。但是&#34; jsonquerytool&#34;给false $ - 这是明确错误的。 $是&#34;根对象/元素&#34;。

对于$..*,这与所有三种实现的结果相同:

[
    [
        "Some short name",
        "Some parent",
        "Some name"
    ],
    [
        "Some short name 2",
        "Some parent 2",
        "Some name 2"
    ],
    "Some short name",
    "Some parent",
    "Some name",
    "Some short name 2",
    "Some parent 2",
    "Some name 2"
]

所以$..[?(@[2] == 'Some name 2')]应该匹配索引&#39; 1的数组......在我看来,jayway做错了。

  

使用JSONPath方括号对前一个路径片段寻址的对象或数组进行操作。 (见http://goessner.net/articles/JsonPath/

Goessner是JSONPath的发明者 - 因此他的实现方式正确! 摘要: jsonquerytool&jayway的实现是错误的。

令人惊讶的是,此查询在所有实现中都按预期工作(尽管jsonquerytool中$false

$[?(@[2] == 'Some name 2')][1]

此版本也有效:

$.[?(@[2] == 'Some name 2')][1]