比较 Java 中的两个 JSON 时忽略数组中的特定节点
Ignore specific node within array when comparing two JSON in Java
我想比较 Java 8 中的两个 JSON 字符串是否相等,但忽略特定的已知节点,这些节点包含预期不同的值并且是可容忍的差异,例如时间戳。
目前使用来自 org.SkyScreamer 的 JSONAssert v1.5.0,我能够 'ignore' 这些节点中的一些,但不能 'ignore' 数组中的节点。
我想要扩展我当前的 JSON 比较器以包含一个自定义,它的第一个 'path' 参数具有数组地址。
JSONComparator customisedJobComparator = new CustomComparator(JSONCompareMode.NON_EXTENSIBLE,
new Customization("id", (o1, o2) -> true),
new Customization("appointmentBookedDate.$date", (o1, o2) -> true),
...
new Customization("someArray[n].timestamp", (o1, o2) -> true) //<--- this is wrong, what is the correct way for this path address?
);
下面的代码是我试图证明一个解决方案; expected/actual JSON 字符串除了 anArray[].id 值外都是相同的。
我希望此测试通过,但因错误而失败:
java.lang.AssertionError: anArray[0] 找不到元素 {"id":"valueA"} 的匹配项
@Test
public void compareJsonStrIgnoringDiffInArray() {
String errorMsg = "";
String expectedJsonStr = "{\"anArray\": [{\"id\": \"valueA\"}, {\"colour\": \"Blue\"}]}";
String actualJsonStr = "{\"anArray\": [{\"id\": \"valueB\"}, {\"colour\": \"Blue\"}]}";
//Create custom comparator which compares two json strings but ignores reporting any differences for anArray[n].id values
//as they are a tolerated difference
Customization customization = new Customization("anArray[n].id", (o1, o2) -> true);
JSONComparator customisedComparator = new CustomComparator(JSONCompareMode.NON_EXTENSIBLE, customization);
JSONAssert.assertEquals(errorMsg, expectedJsonStr, actualJsonStr, customisedComparator);
}
在 javadoc for JSONAssert 中进行了一些挖掘之后,我看到了一个使用对象数组的示例。从那个例子我能够修改你的测试用例:
@Test
public void compareJsonStrIgnoringDiffInArray() throws JSONException {
String errorMsg = "";
String expectedJsonStr = "{\"anArray\": [{\"id\": \"valueA\"}, {\"colour\": \"Blue\"}]}";
String actualJsonStr = "{\"anArray\": [{\"id\": \"valueB\"}, {\"colour\": \"Blue\"}]}";
//Create custom comparator which compares two json strings but ignores reporting any differences for anArray[n].id values
//as they are a tolerated difference
ArrayValueMatcher<Object> arrValMatch = new ArrayValueMatcher<>(new CustomComparator(
JSONCompareMode.NON_EXTENSIBLE,
new Customization("anArray[*].id", (o1, o2) -> true)));
Customization arrayValueMatchCustomization = new Customization("anArray", arrValMatch);
CustomComparator customArrayValueComparator = new CustomComparator(
JSONCompareMode.NON_EXTENSIBLE,
arrayValueMatchCustomization);
JSONAssert.assertEquals(expectedJsonStr, actualJsonStr, customArrayValueComparator);
}
根据我的要求,需要忽略仅出现一次的字段 businessCorrelationId
,data
的每个节点中出现的 effectiveStartDate
。
{
"messageElements": {
"messageStatus": "SUCCESS",
"businessCorrelationId": "a80337639eb40758",
"errorList": []
},
"data": [
{
"referenceId": 1,
"category": "CAT1",
"subCategory": "SUB1",
"effectiveStartDate": "2021-02-08T00:00:00",
"activeFlg": true,
"version": 1
},
{
"referenceId": 2,
"category": "CAT2",
"subCategory": "SUB2",
"effectiveStartDate": "2021-02-08T00:00:00",
"effectiveEndDate": null,
"activeFlg": true,
"version": 1
},
{
"referenceId": 3,
"category": "CAT3",
"subCategory": "SUB3",
"effectiveStartDate": "2021-02-08T00:00:00",
"activeFlg": true,
"version": 1
}
],
"tenant": {
"tenantId": null,
"timeZoneOffset": null,
"name": null
}
}
下面的代码工作正常。
JSONAssert.assertEquals(expectedJson, actualJson, new CustomComparator(JSONCompareMode.LENIENT,
new Customization("data[*].createdTimestamp", (ct1, ct2) -> true),
new Customization("messageElements.businessCorrelationId", (c1, c2) -> true)));
我想比较 Java 8 中的两个 JSON 字符串是否相等,但忽略特定的已知节点,这些节点包含预期不同的值并且是可容忍的差异,例如时间戳。 目前使用来自 org.SkyScreamer 的 JSONAssert v1.5.0,我能够 'ignore' 这些节点中的一些,但不能 'ignore' 数组中的节点。
我想要扩展我当前的 JSON 比较器以包含一个自定义,它的第一个 'path' 参数具有数组地址。
JSONComparator customisedJobComparator = new CustomComparator(JSONCompareMode.NON_EXTENSIBLE,
new Customization("id", (o1, o2) -> true),
new Customization("appointmentBookedDate.$date", (o1, o2) -> true),
...
new Customization("someArray[n].timestamp", (o1, o2) -> true) //<--- this is wrong, what is the correct way for this path address?
);
下面的代码是我试图证明一个解决方案; expected/actual JSON 字符串除了 anArray[].id 值外都是相同的。 我希望此测试通过,但因错误而失败: java.lang.AssertionError: anArray[0] 找不到元素 {"id":"valueA"} 的匹配项
@Test
public void compareJsonStrIgnoringDiffInArray() {
String errorMsg = "";
String expectedJsonStr = "{\"anArray\": [{\"id\": \"valueA\"}, {\"colour\": \"Blue\"}]}";
String actualJsonStr = "{\"anArray\": [{\"id\": \"valueB\"}, {\"colour\": \"Blue\"}]}";
//Create custom comparator which compares two json strings but ignores reporting any differences for anArray[n].id values
//as they are a tolerated difference
Customization customization = new Customization("anArray[n].id", (o1, o2) -> true);
JSONComparator customisedComparator = new CustomComparator(JSONCompareMode.NON_EXTENSIBLE, customization);
JSONAssert.assertEquals(errorMsg, expectedJsonStr, actualJsonStr, customisedComparator);
}
在 javadoc for JSONAssert 中进行了一些挖掘之后,我看到了一个使用对象数组的示例。从那个例子我能够修改你的测试用例:
@Test
public void compareJsonStrIgnoringDiffInArray() throws JSONException {
String errorMsg = "";
String expectedJsonStr = "{\"anArray\": [{\"id\": \"valueA\"}, {\"colour\": \"Blue\"}]}";
String actualJsonStr = "{\"anArray\": [{\"id\": \"valueB\"}, {\"colour\": \"Blue\"}]}";
//Create custom comparator which compares two json strings but ignores reporting any differences for anArray[n].id values
//as they are a tolerated difference
ArrayValueMatcher<Object> arrValMatch = new ArrayValueMatcher<>(new CustomComparator(
JSONCompareMode.NON_EXTENSIBLE,
new Customization("anArray[*].id", (o1, o2) -> true)));
Customization arrayValueMatchCustomization = new Customization("anArray", arrValMatch);
CustomComparator customArrayValueComparator = new CustomComparator(
JSONCompareMode.NON_EXTENSIBLE,
arrayValueMatchCustomization);
JSONAssert.assertEquals(expectedJsonStr, actualJsonStr, customArrayValueComparator);
}
根据我的要求,需要忽略仅出现一次的字段 businessCorrelationId
,data
的每个节点中出现的 effectiveStartDate
。
{
"messageElements": {
"messageStatus": "SUCCESS",
"businessCorrelationId": "a80337639eb40758",
"errorList": []
},
"data": [
{
"referenceId": 1,
"category": "CAT1",
"subCategory": "SUB1",
"effectiveStartDate": "2021-02-08T00:00:00",
"activeFlg": true,
"version": 1
},
{
"referenceId": 2,
"category": "CAT2",
"subCategory": "SUB2",
"effectiveStartDate": "2021-02-08T00:00:00",
"effectiveEndDate": null,
"activeFlg": true,
"version": 1
},
{
"referenceId": 3,
"category": "CAT3",
"subCategory": "SUB3",
"effectiveStartDate": "2021-02-08T00:00:00",
"activeFlg": true,
"version": 1
}
],
"tenant": {
"tenantId": null,
"timeZoneOffset": null,
"name": null
}
}
下面的代码工作正常。
JSONAssert.assertEquals(expectedJson, actualJson, new CustomComparator(JSONCompareMode.LENIENT,
new Customization("data[*].createdTimestamp", (ct1, ct2) -> true),
new Customization("messageElements.businessCorrelationId", (c1, c2) -> true)));