0
# Collection and Map Matchers
1
2
Specialized Hamcrest matchers for validating collections and maps within JSON documents, extending standard Hamcrest capabilities with JSON-specific functionality. These matchers are designed to work seamlessly with JsonPath results and provide enhanced collection validation.
3
4
## Capabilities
5
6
### Collection Size Validation
7
8
Validates collection size using flexible Hamcrest matchers for precise size constraints.
9
10
```java { .api }
11
/**
12
* Creates a matcher for collections that validates size using the provided size matcher
13
* @param sizeMatcher Hamcrest matcher to validate the collection size
14
* @return CollectionMatcher that succeeds when size matches the provided matcher
15
*/
16
public static CollectionMatcher collectionWithSize(Matcher<? super Integer> sizeMatcher);
17
```
18
19
**Usage Examples:**
20
21
```java
22
import static com.jayway.jsonassert.JsonAssert.*;
23
import static com.jayway.jsonpath.matchers.JsonPathMatchers.*;
24
import static org.hamcrest.Matchers.*;
25
26
String json = "{\"users\":[{\"name\":\"Alice\"},{\"name\":\"Bob\"},{\"name\":\"Charlie\"}],\"tags\":[]}";
27
28
// Exact size validation
29
assertThat(json, hasJsonPath("$.users", collectionWithSize(equalTo(3))));
30
31
// Range-based size validation
32
assertThat(json, hasJsonPath("$.users", collectionWithSize(greaterThan(2))));
33
assertThat(json, hasJsonPath("$.users", collectionWithSize(lessThanOrEqualTo(5))));
34
35
// Combined size constraints
36
assertThat(json, hasJsonPath("$.users", collectionWithSize(
37
allOf(greaterThan(1), lessThan(10)))));
38
39
// Empty collection validation
40
assertThat(json, hasJsonPath("$.tags", collectionWithSize(equalTo(0))));
41
42
// Using with fluent assertions
43
with(json)
44
.assertThat("$.users", collectionWithSize(equalTo(3)))
45
.and()
46
.assertThat("$.tags", collectionWithSize(equalTo(0)));
47
```
48
49
### Map Key Validation
50
51
Validates that maps contain specific keys using flexible key matching criteria.
52
53
```java { .api }
54
/**
55
* Creates a matcher for maps that validates the presence of keys matching the provided key matcher
56
* @param keyMatcher Hamcrest matcher to validate map keys
57
* @return Matcher for Map<String, ?> that succeeds when a matching key is found
58
*/
59
public static Matcher<Map<String, ?>> mapContainingKey(Matcher<String> keyMatcher);
60
```
61
62
**Usage Examples:**
63
64
```java
65
String json = "{\"user\":{\"firstName\":\"Alice\",\"lastName\":\"Smith\",\"email\":\"alice@example.com\"}}";
66
67
// Exact key matching
68
assertThat(json, hasJsonPath("$.user", mapContainingKey(equalTo("firstName"))));
69
70
// Pattern-based key matching
71
assertThat(json, hasJsonPath("$.user", mapContainingKey(startsWith("first"))));
72
assertThat(json, hasJsonPath("$.user", mapContainingKey(endsWith("Name"))));
73
assertThat(json, hasJsonPath("$.user", mapContainingKey(containsString("email"))));
74
75
// Case-insensitive key matching
76
assertThat(json, hasJsonPath("$.user", mapContainingKey(equalToIgnoringCase("FIRSTNAME"))));
77
78
// Combined key validation
79
assertThat(json, hasJsonPath("$.user", allOf(
80
mapContainingKey(equalTo("firstName")),
81
mapContainingKey(equalTo("lastName")),
82
mapContainingKey(equalTo("email"))
83
)));
84
85
// Using with fluent assertions
86
with(json)
87
.assertThat("$.user", mapContainingKey(equalTo("firstName")))
88
.and()
89
.assertThat("$.user", mapContainingKey(endsWith("Name")));
90
```
91
92
### Map Value Validation
93
94
Validates that maps contain specific values using flexible value matching criteria.
95
96
```java { .api }
97
/**
98
* Creates a matcher for maps that validates the presence of values matching the provided value matcher
99
* @param valueMatcher Hamcrest matcher to validate map values
100
* @return Matcher for Map<?, V> that succeeds when a matching value is found
101
*/
102
public static <V> Matcher<? super Map<?, V>> mapContainingValue(Matcher<? super V> valueMatcher);
103
```
104
105
**Usage Examples:**
106
107
```java
108
String json = "{\"config\":{\"timeout\":30,\"retries\":3,\"enabled\":true,\"url\":\"https://api.example.com\"}}";
109
110
// Exact value matching
111
assertThat(json, hasJsonPath("$.config", mapContainingValue(equalTo(30))));
112
assertThat(json, hasJsonPath("$.config", mapContainingValue(equalTo(true))));
113
114
// Type-specific value matching
115
assertThat(json, hasJsonPath("$.config", mapContainingValue(instanceOf(String.class))));
116
assertThat(json, hasJsonPath("$.config", mapContainingValue(instanceOf(Integer.class))));
117
assertThat(json, hasJsonPath("$.config", mapContainingValue(instanceOf(Boolean.class))));
118
119
// String value pattern matching
120
assertThat(json, hasJsonPath("$.config", mapContainingValue(startsWith("https://"))));
121
assertThat(json, hasJsonPath("$.config", mapContainingValue(containsString("api"))));
122
123
// Numeric value range matching
124
assertThat(json, hasJsonPath("$.config", mapContainingValue(greaterThan(0))));
125
assertThat(json, hasJsonPath("$.config", mapContainingValue(lessThanOrEqualTo(100))));
126
127
// Combined value validation
128
assertThat(json, hasJsonPath("$.config", allOf(
129
mapContainingValue(equalTo(30)),
130
mapContainingValue(equalTo(true)),
131
mapContainingValue(startsWith("https://"))
132
)));
133
134
// Using with fluent assertions
135
with(json)
136
.assertThat("$.config", mapContainingValue(equalTo(30)))
137
.and()
138
.assertThat("$.config", mapContainingValue(instanceOf(String.class)));
139
```
140
141
### Empty Collection Validation
142
143
Validates that collections are empty with type-safe handling.
144
145
```java { .api }
146
/**
147
* Creates a matcher that validates collections are empty
148
* @return Matcher for Collection<Object> that succeeds for empty collections
149
*/
150
public static Matcher<Collection<Object>> emptyCollection();
151
```
152
153
**Usage Examples:**
154
155
```java
156
String json = "{\"activeUsers\":[],\"completedTasks\":[],\"pendingItems\":[{\"id\":1}]}";
157
158
// Empty collection validation
159
assertThat(json, hasJsonPath("$.activeUsers", emptyCollection()));
160
assertThat(json, hasJsonPath("$.completedTasks", emptyCollection()));
161
162
// Non-empty collection validation (negated)
163
assertThat(json, hasJsonPath("$.pendingItems", not(emptyCollection())));
164
165
// Combined with size validation
166
assertThat(json, hasJsonPath("$.activeUsers", allOf(
167
emptyCollection(),
168
collectionWithSize(equalTo(0))
169
)));
170
171
// Using with fluent assertions
172
with(json)
173
.assertThat("$.activeUsers", emptyCollection())
174
.and()
175
.assertThat("$.completedTasks", emptyCollection())
176
.and()
177
.assertThat("$.pendingItems", not(emptyCollection()));
178
```
179
180
## Advanced Usage Patterns
181
182
### Nested Collection Validation
183
184
Combining collection matchers with JsonPath expressions for deep validation:
185
186
```java
187
String json = "{\"departments\":[{\"name\":\"Engineering\",\"employees\":[{\"name\":\"Alice\"},{\"name\":\"Bob\"}]},{\"name\":\"Marketing\",\"employees\":[]}]}";
188
189
// Validate nested collection sizes
190
assertThat(json, hasJsonPath("$.departments", collectionWithSize(equalTo(2))));
191
assertThat(json, hasJsonPath("$.departments[0].employees", collectionWithSize(equalTo(2))));
192
assertThat(json, hasJsonPath("$.departments[1].employees", emptyCollection()));
193
194
// Validate all employee collections
195
assertThat(json, hasJsonPath("$.departments[*].employees", everyItem(
196
instanceOf(Collection.class))));
197
198
// Complex nested validation
199
with(json)
200
.assertThat("$.departments", collectionWithSize(greaterThan(1)))
201
.and()
202
.assertThat("$.departments[0]", mapContainingKey(equalTo("employees")))
203
.and()
204
.assertThat("$.departments[0].employees", collectionWithSize(greaterThan(0)));
205
```
206
207
### Map Structure Validation
208
209
Comprehensive map validation combining key and value matchers:
210
211
```java
212
String json = "{\"apiResponse\":{\"status\":\"success\",\"code\":200,\"data\":{\"count\":5,\"items\":[]}}}";
213
214
// Comprehensive map validation
215
assertThat(json, hasJsonPath("$.apiResponse", allOf(
216
mapContainingKey(equalTo("status")),
217
mapContainingKey(equalTo("code")),
218
mapContainingKey(equalTo("data")),
219
mapContainingValue(equalTo("success")),
220
mapContainingValue(equalTo(200))
221
)));
222
223
// Nested map validation
224
assertThat(json, hasJsonPath("$.apiResponse.data", allOf(
225
mapContainingKey(equalTo("count")),
226
mapContainingKey(equalTo("items")),
227
mapContainingValue(instanceOf(Integer.class)),
228
mapContainingValue(instanceOf(Collection.class))
229
)));
230
231
// Value type and content validation
232
with(json)
233
.assertThat("$.apiResponse", mapContainingValue(equalTo("success")))
234
.and()
235
.assertThat("$.apiResponse.data", mapContainingValue(greaterThan(0)))
236
.and()
237
.assertThat("$.apiResponse.data.items", emptyCollection());
238
```
239
240
## Integration with JsonPath Results
241
242
These matchers are specifically designed to work with JsonPath evaluation results:
243
244
```java
245
import com.jayway.jsonpath.JsonPath;
246
247
String json = "{\"data\":{\"users\":[{\"active\":true},{\"active\":false}],\"metadata\":{\"total\":2,\"page\":1}}}";
248
249
// Direct JsonPath evaluation with matchers
250
List<Object> users = JsonPath.read(json, "$.data.users");
251
assertThat(users, collectionWithSize(equalTo(2)));
252
253
Map<String, Object> metadata = JsonPath.read(json, "$.data.metadata");
254
assertThat(metadata, mapContainingKey(equalTo("total")));
255
assertThat(metadata, mapContainingValue(equalTo(2)));
256
257
// Combined with JsonPath matchers
258
assertThat(json, isJson(allOf(
259
withJsonPath("$.data.users", collectionWithSize(greaterThan(1))),
260
withJsonPath("$.data.metadata", mapContainingKey(equalTo("total"))),
261
withJsonPath("$.data.metadata", mapContainingValue(greaterThan(0)))
262
)));
263
```
264
265
## Type Safety and Generic Support
266
267
The collection matchers provide type-safe operation while maintaining flexibility:
268
269
```java
270
// Type-safe value matching
271
Matcher<Map<String, String>> stringMapMatcher = mapContainingValue(startsWith("prefix"));
272
Matcher<Map<String, Integer>> intMapMatcher = mapContainingValue(greaterThan(0));
273
274
// Generic collection matching
275
Matcher<Collection<String>> stringCollectionMatcher = collectionWithSize(greaterThan(0));
276
277
// Usage maintains type safety
278
String json = "{\"stringMap\":{\"key\":\"prefixValue\"},\"intMap\":{\"count\":5}}";
279
assertThat(json, hasJsonPath("$.stringMap", stringMapMatcher));
280
assertThat(json, hasJsonPath("$.intMap", intMapMatcher));
281
```