jsonpathでメンバーをカウントしますか?


103

JsonPathを使用してメンバーの数をカウントすることは可能ですか?

Spring MVCテストを使用して、生成するコントローラーをテストしています

{"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を使用してそれらを数えることによって。出来ますか?代替ソリューションも歓迎します。

回答:


233

配列のサイズをテストするには: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-library次のコードを
Adam Michalik

1
サイズがわからず、それを取得したい場合はどうなりますか?
zygimantus 2016年

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);
}

実際、2番目のアプローチは最初のアプローチよりもパフォーマンスが良いように見えます。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のコンテンツは常に配列であると想定しました]

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.