นับสมาชิกด้วย jsonpath?


103

เป็นไปได้ไหมที่จะนับจำนวนสมาชิกโดยใช้ JsonPath?

ใช้การทดสอบสปริง 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 เป็นไปได้ไหม? ทางเลือกอื่นยินดีต้อนรับเช่นกัน

คำตอบ:


236

ในการทดสอบขนาดของอาร์เรย์ :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: code.google.com/p/hamcrest/wiki/HamcrestDistributables
Adam Michalik

1
จะเป็นอย่างไรถ้าใครไม่ทราบขนาดและต้องการรับมัน?
zygimantus

2
@ menuka-ishan - ฉันไม่คิดว่ามันเลิกใช้แล้วตาม: MockMvcResultMatchers.jsonPath () javadoc
lopisan

@zygimantus คุณต้องนับขนาดของฟิลด์ทั้งหมดใน Object / Array ของคุณไม่ว่าจะจากซอร์สโค้ดหรือการตรวจสอบเครื่องมือของนักพัฒนาเว็บเบราว์เซอร์ของการตอบสนอง
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ใน classpath ของคุณ (ซึ่งเป็นกรณีของฉัน) การทดสอบด้วยวิธีต่อไปนี้อาจเป็นวิธีแก้ปัญหาที่เป็นไปได้:

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

[หมายเหตุ: ฉันคิดว่าเนื้อหาของ json เป็นอาร์เรย์เสมอ]

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.