Skip to content

Commit 230ba92

Browse files
author
ctruchi
committed
Support wildcards in Customization.path
1 parent 8c9cf78 commit 230ba92

File tree

2 files changed

+163
-6
lines changed

2 files changed

+163
-6
lines changed

src/main/java/org/skyscreamer/jsonassert/Customization.java

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,98 @@
11
package org.skyscreamer.jsonassert;
22

3+
import java.util.regex.Pattern;
4+
35
/**
46
* Associates a custom matcher to a specific jsonpath.
57
*/
68
public final class Customization {
7-
private final String path;
9+
private final Pattern path;
810
private final ValueMatcher<Object> comparator;
911

1012
public Customization(String path, ValueMatcher<Object> comparator) {
1113
assert path != null;
1214
assert comparator != null;
13-
this.path = path;
15+
this.path = Pattern.compile(buildPattern(path));
1416
this.comparator = comparator;
1517
}
1618

19+
private String buildPattern(String path) {
20+
return buildPatternLevel1(path);
21+
}
22+
23+
private String buildPatternLevel1(String path) {
24+
String regex = "\\*\\*\\.";
25+
String replacement = "(?:.+\\.)?";
26+
27+
StringBuilder sb = new StringBuilder();
28+
String[] parts = path.split(regex);
29+
for (int i = 0; i < parts.length; i++) {
30+
String part = parts[i];
31+
32+
sb.append(buildPatternLevel2(part));
33+
if (i < parts.length - 1) {
34+
sb.append(replacement);
35+
}
36+
}
37+
38+
return sb.toString();
39+
}
40+
41+
private String buildPatternLevel2(String s) {
42+
if (s.isEmpty()) {
43+
return "";
44+
}
45+
String regex = "\\*\\*";
46+
String replacement = ".+";
47+
48+
StringBuilder sb = new StringBuilder();
49+
String[] parts = s.split(regex);
50+
for (int i = 0; i < parts.length; i++) {
51+
String part = parts[i];
52+
53+
sb.append(buildPatternLevel3(part));
54+
if (i < parts.length - 1) {
55+
sb.append(replacement);
56+
}
57+
}
58+
return sb.toString();
59+
}
60+
61+
private String buildPatternLevel3(String s) {
62+
if (s.isEmpty()) {
63+
return "";
64+
}
65+
66+
String regex = "\\*";
67+
String replacement = "[^\\.]+";
68+
69+
StringBuilder sb = new StringBuilder();
70+
String[] parts = s.split(regex);
71+
for (int i = 0; i < parts.length; i++) {
72+
String part = parts[i];
73+
74+
sb.append(Pattern.quote(part));
75+
if (i < parts.length - 1) {
76+
sb.append(replacement);
77+
}
78+
}
79+
return sb.toString();
80+
}
81+
1782
public static Customization customization(String path, ValueMatcher<Object> comparator) {
1883
return new Customization(path, comparator);
1984
}
2085

2186
public boolean appliesToPath(String path) {
22-
return this.path.equals(path);
87+
return this.path.matcher(path).matches();
2388
}
2489

2590
/**
2691
* Return true if actual value matches expected value using this
2792
* Customization's comparator. Calls to this method should be replaced by
2893
* calls to matches(String prefix, Object actual, Object expected,
2994
* JSONCompareResult result).
30-
*
95+
*
3196
* @param actual
3297
* JSON value being tested
3398
* @param expected
@@ -38,12 +103,12 @@ public boolean appliesToPath(String path) {
38103
public boolean matches(Object actual, Object expected) {
39104
return comparator.equal(actual, expected);
40105
}
41-
106+
42107
/**
43108
* Return true if actual value matches expected value using this
44109
* Customization's comparator. The equal method used for comparison depends
45110
* on type of comparator.
46-
*
111+
*
47112
* @param prefix
48113
* JSON path of the JSON item being tested (only used if
49114
* comparator is a LocationAwareValueMatcher)

src/test/java/org/skyscreamer/jsonassert/JSONCustomComparatorTest.java

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,75 @@ public class JSONCustomComparatorTest {
3535
" }\n" +
3636
"}";
3737

38+
String simpleWildcardActual = "{\n" +
39+
" \"foo\": {\n" +
40+
" \"bar1\": {\n" +
41+
" \"baz\": \"actual\"\n" +
42+
" },\n" +
43+
" \"bar2\": {\n" +
44+
" \"baz\": \"actual\"\n" +
45+
" }\n" +
46+
" }\n" +
47+
"}";
48+
String simpleWildcardExpected = "{\n" +
49+
" \"foo\": {\n" +
50+
" \"bar1\": {\n" +
51+
" \"baz\": \"expected\"\n" +
52+
" },\n" +
53+
" \"bar2\": {\n" +
54+
" \"baz\": \"expected\"\n" +
55+
" }\n" +
56+
" }\n" +
57+
"}";
58+
59+
String deepWildcardActual = "{\n" +
60+
" \"root\": {\n" +
61+
" \"baz\": \"actual\",\n" +
62+
" \"foo\": {\n" +
63+
" \"baz\": \"actual\",\n" +
64+
" \"bar\": {\n" +
65+
" \"baz\": \"actual\"\n" +
66+
" }\n" +
67+
" }\n" +
68+
" }\n" +
69+
"}";
70+
String deepWildcardExpected = "{\n" +
71+
" \"root\": {\n" +
72+
" \"baz\": \"expected\",\n" +
73+
" \"foo\": {\n" +
74+
" \"baz\": \"expected\",\n" +
75+
" \"bar\": {\n" +
76+
" \"baz\": \"expected\"\n" +
77+
" }\n" +
78+
" }\n" +
79+
" }\n" +
80+
"}";
81+
82+
String rootDeepWildcardActual = "{\n" +
83+
" \"baz\": \"actual\",\n" +
84+
" \"root\": {\n" +
85+
" \"baz\": \"actual\",\n" +
86+
" \"foo\": {\n" +
87+
" \"baz\": \"actual\",\n" +
88+
" \"bar\": {\n" +
89+
" \"baz\": \"actual\"\n" +
90+
" }\n" +
91+
" }\n" +
92+
" }\n" +
93+
"}";
94+
String rootDeepWildcardExpected = "{\n" +
95+
" \"baz\": \"expected\",\n" +
96+
" \"root\": {\n" +
97+
" \"baz\": \"expected\",\n" +
98+
" \"foo\": {\n" +
99+
" \"baz\": \"expected\",\n" +
100+
" \"bar\": {\n" +
101+
" \"baz\": \"expected\"\n" +
102+
" }\n" +
103+
" }\n" +
104+
" }\n" +
105+
"}";
106+
38107
int comparatorCallCount = 0;
39108
ValueMatcher<Object> comparator = new ValueMatcher<Object>() {
40109
@Override
@@ -60,4 +129,27 @@ public void whenDeepPathMatchesCallCustomMatcher() throws JSONException {
60129
assertEquals(1, comparatorCallCount);
61130
}
62131

132+
@Test
133+
public void whenSimpleWildcardPathMatchesCallCustomMatcher() throws JSONException {
134+
JSONComparator jsonCmp = new CustomComparator(JSONCompareMode.STRICT, new Customization("foo.*.baz", comparator));
135+
JSONCompareResult result = compareJSON(simpleWildcardExpected, simpleWildcardActual, jsonCmp);
136+
assertTrue(result.getMessage(), result.passed());
137+
assertEquals(2, comparatorCallCount);
138+
}
139+
140+
@Test
141+
public void whenDeepWildcardPathMatchesCallCustomMatcher() throws JSONException {
142+
JSONComparator jsonCmp = new CustomComparator(JSONCompareMode.STRICT, new Customization("root.**.baz", comparator));
143+
JSONCompareResult result = compareJSON(deepWildcardExpected, deepWildcardActual, jsonCmp);
144+
assertTrue(result.getMessage(), result.passed());
145+
assertEquals(3, comparatorCallCount);
146+
}
147+
148+
@Test
149+
public void whenRootDeepWildcardPathMatchesCallCustomMatcher() throws JSONException {
150+
JSONComparator jsonCmp = new CustomComparator(JSONCompareMode.STRICT, new Customization("**.baz", comparator));
151+
JSONCompareResult result = compareJSON(rootDeepWildcardExpected, rootDeepWildcardActual, jsonCmp);
152+
assertTrue(result.getMessage(), result.passed());
153+
assertEquals(4, comparatorCallCount);
154+
}
63155
}

0 commit comments

Comments
 (0)