Skip to content

Commit 5d5d947

Browse files
committed
Merge pull request skyscreamer#31 from albx79/jsonpath
Custom comparator per path
2 parents 8f4a25b + f49da4b commit 5d5d947

File tree

6 files changed

+125
-6
lines changed

6 files changed

+125
-6
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,12 @@ public Behavior butExtraFieldsAre(Allowance allowance) {
7777
public Behavior with(Customization customization) {
7878
return Builder.from(this).add(customization).build();
7979
}
80+
81+
public Customization getCustomization(String path) {
82+
for (Customization c : customizations) {
83+
if (c.appliesToPath(path))
84+
return c;
85+
}
86+
return null;
87+
}
8088
}

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,24 @@
44

55
public final class Customization {
66
private final String path;
7-
private final Matcher<?> matcher;
7+
private final EqualsComparator<Object> comparator;
88

9-
public Customization(String path, Matcher<?> matcher) {
9+
public Customization(String path, EqualsComparator<Object> comparator) {
10+
assert path != null;
11+
assert comparator != null;
1012
this.path = path;
11-
this.matcher = matcher;
13+
this.comparator = comparator;
1214
}
1315

14-
public static Customization customization(String path, Matcher<?> matcher) {
15-
return new Customization(path, matcher);
16+
public static Customization customization(String path, EqualsComparator<Object> comparator) {
17+
return new Customization(path, comparator);
1618
}
19+
20+
public boolean appliesToPath(String path) {
21+
return this.path.equals(path);
22+
}
23+
24+
public boolean matches(Object actual, Object expected) {
25+
return comparator.equal(actual, expected);
26+
}
1727
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.skyscreamer.jsonassert;
2+
3+
public interface EqualsComparator<T> {
4+
5+
boolean equal(T o1, T o2);
6+
7+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.skyscreamer.jsonassert;
2+
3+
import org.hamcrest.Matcher;
4+
5+
/**
6+
* Delegate equality comparison to an org.hamcrest.Matcher
7+
* @param <T>
8+
*/
9+
public final class HamcrestEqualsComparator<T> implements EqualsComparator<T> {
10+
11+
private final Matcher<?> matcher;
12+
13+
public HamcrestEqualsComparator(Matcher<?> matcher) {
14+
this.matcher = matcher;
15+
}
16+
17+
/**
18+
* The matcher is invoked on the first parameter, ignoring the second
19+
* @param o1
20+
* @param o2 ignored
21+
* @return true if mather matches o1
22+
*/
23+
@Override
24+
public boolean equal(T o1, T o2) {
25+
return matcher.matches(o1);
26+
}
27+
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,12 @@ private static String qualify(String prefix, String key) {
122122

123123
private static void compareValues(String fullKey, Object expectedValue, Object actualValue, Behavior behavior, JSONCompareResult result) throws JSONException
124124
{
125-
if (expectedValue.getClass().isAssignableFrom(actualValue.getClass())) {
125+
Customization customization = behavior.getCustomization(fullKey);
126+
if (customization != null) {
127+
if (!customization.matches(actualValue, expectedValue)) {
128+
result.fail(fullKey, expectedValue, actualValue);
129+
}
130+
} else if (expectedValue.getClass().isAssignableFrom(actualValue.getClass())) {
126131
if (expectedValue instanceof JSONArray) {
127132
compareJSONArray(fullKey , (JSONArray)expectedValue, (JSONArray)actualValue, behavior, result);
128133
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package org.skyscreamer.jsonassert;
2+
3+
import org.hamcrest.BaseMatcher;
4+
import org.hamcrest.Description;
5+
import org.hamcrest.Matcher;
6+
import org.json.JSONException;
7+
import org.junit.Test;
8+
9+
import static org.junit.Assert.assertThat;
10+
import static org.junit.Assert.assertTrue;
11+
import static org.skyscreamer.jsonassert.Behavior.STRICT;
12+
import static org.skyscreamer.jsonassert.Customization.customization;
13+
import static org.skyscreamer.jsonassert.JSONCompare.compareJSON;
14+
15+
public class JSONBehaviourTest {
16+
17+
String actual = "{\"first\":\"actual\", \"second\":1}";
18+
String expected = "{\"first\":\"expected\", \"second\":1}";
19+
20+
String deepActual = "{\n" +
21+
" \"outer\":\n" +
22+
" {\n" +
23+
" \"inner\":\n" +
24+
" {\n" +
25+
" \"value\": \"actual\",\n" +
26+
" \"otherValue\": \"foo\"\n" +
27+
" }\n" +
28+
" }\n" +
29+
"}";
30+
String deepExpected = "{\n" +
31+
" \"outer\":\n" +
32+
" {\n" +
33+
" \"inner\":\n" +
34+
" {\n" +
35+
" \"value\": \"expected\",\n" +
36+
" \"otherValue\": \"foo\"\n" +
37+
" }\n" +
38+
" }\n" +
39+
"}";
40+
41+
EqualsComparator<Object> comparator = new EqualsComparator<Object>() {
42+
@Override
43+
public boolean equal(Object o1, Object o2) {
44+
return o1.toString().equals("actual") && o2.toString().equals("expected");
45+
}
46+
};
47+
48+
@Test
49+
public void whenPathMatchesInCustomizationThenCallCustomMatcher() throws JSONException {
50+
Behavior behavior = STRICT.with(customization("first", comparator));
51+
JSONCompareResult result = compareJSON(expected, actual, behavior);
52+
assertTrue(result.getMessage(), result.passed());
53+
}
54+
55+
@Test
56+
public void whenDeepPathMatchesCallCustomMatcher() throws JSONException {
57+
Behavior behavior = STRICT.with(customization("outer.inner.value", comparator));
58+
JSONCompareResult result = compareJSON(deepExpected, deepActual, behavior);
59+
assertTrue(result.getMessage(), result.passed());
60+
}
61+
62+
}

0 commit comments

Comments
 (0)