用jsonpath计数成员?


103

使用JsonPath是否可以计算成员数?

使用Spring MVC Test我正在测试生成的控制器

{"foo": "oof", "bar": "rab"}

standaloneSetup(new FooController(fooService)).build()
            .perform(get("/something").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
            .andExpect(jsonPath("$.foo").value("oof"))
            .andExpect(jsonPath("$.bar").value("rab"));

我想确保生成的json中没有其他成员。希望通过使用jsonPath计数它们。可能吗?也欢迎其他解决方案。

Answers:


232

要测试数组的大小:jsonPath("$", hasSize(4))

要计算对象的成员:jsonPath("$.*", hasSize(4))


即测试API返回4个项目的数组

接受值: [1,2,3,4]

mockMvc.perform(get(API_URL))
       .andExpect(jsonPath("$", hasSize(4)));

测试API是否返回包含2个成员的对象

接受值: {"foo": "oof", "bar": "rab"}

mockMvc.perform(get(API_URL))
       .andExpect(jsonPath("$.*", hasSize(2)));

我正在使用Hamcrest版本1.3和Spring Test 3.2.5。

hasSize(int)javadoc

注意:您需要包括hamcrest-library依赖项,并且import static org.hamcrest.Matchers.*;hasSize()才能起作用。


2
@mattb-如果使用Maven,则不要添加hamcrest-all为依赖项,而是使用hamcrest-librarycode.google.com/p/hamcrest/wiki/HamcrestDistributables
Adam Michalik 2015年

1
如果一个人不知道尺寸并想得到它该怎么办?
zygimantus '16

2
@ menuka-ishan-我认为它不被弃用,根据:MockMvcResultMatchers.jsonPath() javadoc
lopisan

@zygimantus,您必须从源代码或Web浏览器开发人员工具检查响应中计算出对象/数组上所有字段的大小。
cellepo

12

您还可以使用jsonpath内的方法,因此代替

mockMvc.perform(get(API_URL))
   .andExpect(jsonPath("$.*", hasSize(2)));

你可以做

mockMvc.perform(get(API_URL))
   .andExpect(jsonPath("$.length()", is(2)));

7

我们可以使用JsonPath功能size()或者length(),就像这样:

@Test
public void givenJson_whenGetLengthWithJsonPath_thenGetLength() {
    String jsonString = "{'username':'jhon.user','email':'jhon@company.com','age':'28'}";

    int length = JsonPath
        .parse(jsonString)
        .read("$.length()");

    assertThat(length).isEqualTo(3);
}

或者只是解析net.minidev.json.JSONObject并获取大小:

@Test
public void givenJson_whenParseObject_thenGetSize() {
    String jsonString = "{'username':'jhon.user','email':'jhon@company.com','age':'28'}";

    JSONObject jsonObject = (JSONObject) JSONValue.parse(jsonString);

    assertThat(jsonObject)
        .size()
        .isEqualTo(3);
}

确实,第二种方法看起来比第一种方法表现更好。我进行了JMH性能测试,并得到以下结果:

| Benchmark                                       | Mode  | Cnt | Score       | Error        | Units |
|-------------------------------------------------|-------|-----|-------------|--------------|-------|
| JsonPathBenchmark.benchmarkJSONObjectParse      | thrpt | 5   | 3241471.044 | ±1718855.506 | ops/s |
| JsonPathBenchmark.benchmarkJsonPathObjectLength | thrpt | 5   | 1680492.243 | ±132492.697  | ops/s |

示例代码可以在这里找到。


4

今天自己一直在处理这个问题。在可用的断言中似乎并没有实现这一点。但是,有一种方法可以传入org.hamcrest.Matcher对象。这样,您可以执行以下操作:

final int count = 4; // expected count

jsonPath("$").value(new BaseMatcher() {
    @Override
    public boolean matches(Object obj) {
        return obj instanceof JSONObject && ((JSONObject) obj).size() == count;
    }

    @Override
    public void describeTo(Description description) {
        // nothing for now
    }
})

0

如果您没有com.jayway.jsonassert.JsonAssert在类路径上(我就是这种情况),则可以通过以下方式进行测试:

assertEquals(expectedLength, ((net.minidev.json.JSONArray)parsedContent.read("$")).size());

[注意:我假设json的内容始终是数组]

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.