title: Spring MockMvc: match a collection of JSON objects in any order
body: <p>I have an API endpoint which, when called with GET, returns an array of JSON objects in the body, like this:</p>
  
  <pre><code>[
    {"id": "321", "created": "2019-03-01", "updated": "2019-03-15"},
    {"id": "123", "created": "2019-03-02", "updated": "2019-03-16"}
  ]
  </code></pre>
  
  <p>I would like to check the body with a Spring MockMvc test case.
  The statement currently looks like this:</p>
  
  <pre><code>mockMvc.perform(get("/myapi/v1/goodstuff").
    andExpect(status().isOk()).
    andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)).
    andExpect(jsonPath("$.*", isA(ArrayList.class))).
    andExpect(jsonPath("$.*", hasSize(2))).
    andExpect(jsonPath("$[0].id", is("321"))).
    andExpect(jsonPath("$[0].created", is("2019-03-01"))).
    andExpect(jsonPath("$[0].updated*", is("2019-03-15"))).
    andExpect(jsonPath("$[1].id", is("1232"))).
    andExpect(jsonPath("$[1].created", is("2019-03-02"))).
    andExpect(jsonPath("$[1].updated*", is("2019-03-16")));
  </code></pre>
  
  <p>However, the implementation of my API doesn't guarantee the order of JSON object in the returned array.
  Were this an array of strings, I would solve this via matcher generated by <code>org.hamcrest.collection.IsIterableContainingInAnyOrder&lt;T&gt;.containsInAnyOrder</code>.
  But I cannot see any suitable matcher for my situation <a href="http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/collection/IsIterableContainingInAnyOrder.html" rel="noreferrer">in their doc</a>, nor any clue in the description of <code>jsonPath</code> method <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/web/servlet/result/MockMvcResultMatchers.html#jsonPath-java.lang.String-org.hamcrest.Matcher-" rel="noreferrer">in Spring docs</a></p>
  
  <p>From a quick search I didn't manage find anything related to my situation on SO, either, beyond a <a href="https://stackoverflow.com/questions/15371022/springmvc-mockmvc-jsonpath-compare-list-of-strings">list of strings situation</a> I described above.
  Of course, I could convert JSON objects to strings.</p>
  
  <p>But I'm wondering, could I solve this problem for a list of JSON objects, comparing each of the fields of each objects one-by-one (like shown in the code snippet above), but ignoring the order of objects in the collection?</p>
  
  <p><strong>Update</strong>: <a href="https://stackoverflow.com/users/2810730/zgurskyi">Zgurskyi</a> <a href="https://stackoverflow.com/a/55269321/5722863">has suggested</a> a solution that helps with my original simplified example. However, with a real-life practical example there are 2 more inputs:</p>
  
  <ul>
  <li>the number of fields is 10-20 instead of 3</li>
  <li>not all of matchers are plain <code>is</code>, for instance:</li>
  </ul>
  
  <p>(a bit closer to my original code)</p>
  
  <pre><code>mockMvc.perform(get("/myapi/v1/greatstuff").
        andExpect(status().isOk()).
        andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)).
        andExpect(jsonPath("$.*", isA(ArrayList.class))).
        andExpect(jsonPath("$.*", hasSize(2))).
        andExpect(jsonPath("$[0].id", is("321"))).
        andExpect(jsonPath("$[0].did", anything())).
        andExpect(jsonPath("$[0].createdTs", startsWith("2019-03-01"))).
        andExpect(jsonPath("$[0].updatedTs", startsWith("2019-03-15"))).
        andExpect(jsonPath("$[0].name", equalToIgnoringCase("wat"))).
        andExpect(jsonPath("$[0].stringValues", containsInAnyOrder("a","b","c"))).
        andExpect(jsonPath("$[1].id", is("1232"))).
        andExpect(jsonPath("$[1].did", anything())).
        andExpect(jsonPath("$[1].createdTs", startsWith("2019-03-01"))).
        andExpect(jsonPath("$[1].updatedTs", startsWith("2019-03-15"))).
        andExpect(jsonPath("$[1].name", equalToIgnoringCase("taw"))).
        andExpect(jsonPath("$[1].stringValues", containsInAnyOrder("d","e","f"))).
        andReturn();
  </code></pre>
  
  <p>So far it seems that I can't do anything better than implementing my own matcher class. </p>
  
  <p>Or...can I?</p>