【问题标题】:Verify the existence of an array of root nodes with JSONpath使用 JSONpath 验证根节点数组是否存在
【发布时间】:2017-11-17 13:24:43
【问题描述】:

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

assertThat(json, hasJsonPath("$.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 个根节点是否存在于响应中并且是有效路径。

在将我的 API 响应串入一个“json”变量后,我尝试了如下操作:

JsonPath jp = new JsonPath(json);

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

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

有没有办法解决这个问题?

【问题讨论】:

    标签: java json rest hamcrest


    【解决方案1】:

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

    例如:

    // 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")));
    

    【讨论】:

    • 我将 $ 打印到控制台,可以看到根节点的值也被返回。我希望使用某种数组方法只提取没有它们的值的根节点。顺便说一句,哪个库会将“is”方法添加到项目中?它抛出一个错误
    • 如果这里的目的是验证有两个根节点并且这些根节点的名称是:“tool”和“book”,那么上面的代码就是这样做的。您不需要 需要 将根节点名称提取到 String[] 中以做出该断言。关于您的另一个问题:is 的完全限定路径是org.hamcrest.Matchers,即它由与hasItem 相同的类提供。
    • 我更新了问题,展示了如何将根节点名称提取到 String[] 中,并展示了如何在 hasJsonPath 调用中隐藏整个匹配器。
    • 太棒了,@glytching。在我将正确的 hamcrest 类添加到您的 sn-p 后,我开始看到一些有趣的结果。我现在可以看到没有它们的值的根节点的提取。如果我想验证根节点不为空或不为空而不实际提取它们的值,这可以实现吗?
    • 无论您执行什么断言,一切都从解析 JSON 开始,这会导致节点名称 值被反序列化。您不能只反序列化节点名称,因为JsonPath 将始终反序列化整个 JSON 字符串。我认为您应该专注于您的断言,而不必担心 JsonPath 是否(从您的角度来看是多余的)反序列化了这些值。上面的答案向您展示了三种针对根节点进行断言并完全忽略值的方式。
    猜你喜欢
    • 1970-01-01
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 2015-01-07
    • 2017-06-12
    • 1970-01-01
    相关资源
    最近更新 更多