使用 JSONpath 验证根节点数组是否存在

Verify the existence of an array of root nodes with JSONpath

从下面的 JSON 响应中,我可以使用 hamcrest 库中的此方法验证 JSON 路径中是否存在根节点:

assertThat(json, hasJsonPath("$.tool"));

这将检查名为 'tool' 的根节点是否存在。

{
    "tool": 
    {
        "jsonpath": 
        {
            "creator": 
            {
                "name": "Jayway Inc.",
                "location": 
                [
                    "Malmo",
                    "San Francisco",
                    "Helsingborg"
                ]
            }
        }
    },

    "book": 
    [
        {
            "title": "Beginning JSON",
            "price": 49.99
        },

        {
            "title": "JSON at Work",
            "price": 29.99
        }
    ]
}

如果我想使用存储在变量中的数组来检查两个根节点(工具和书籍)是否存在,如何实现?我不关心它们的值或子节点的值。我只想验证这 2 个根节点是否存在于响应中并且是有效路径。

在 'json' 变量中加入我的 API 响应后,我尝试了这样的操作:

JsonPath jp = new JsonPath(json);

String[] rootNodes = {"tool", "book"};
assertThat(json, hasJsonPath(json.getString(rootNodes)));

但是编译器对 getString 方法不满意。

有办法解决这个问题吗?

根节点运算符是 $,因此您只需将 $ 读入映射,该映射将以您的根节点名称为键。

例如:

// Approach 1
Map<String, Object> read = JsonPath.read(json, "$");

assertThat(read.size(), is(2));

assertThat(read.keySet(), hasItem("tool"));
assertThat(read.keySet(), hasItem("book"));

// Approach 2: if you want a String[] then ...
String[] rootNodeNames = read.keySet().toArray(new String[read.size()]);
assertThat(rootNodeNames, Matchers.both(arrayWithSize(2)).and(arrayContainingInAnyOrder("book", "tool")));

// Approach 3: if you want to hide it all behind the hasJsonPath() matcher
// note: each of these assertion will cause your JSON string to be parsed 
// so it's more efficient to do that once and assert against the 
// resulting map as I did above
assertThat(json, hasJsonPath("$", Matchers.hasKey("tool")));
assertThat(json, hasJsonPath("$", Matchers.hasKey("book")));