我正在寻找一个JSON解析库,支持比较忽略子顺序的两个JSON对象,特别是用于从web服务返回的单元测试JSON。
有任何主要的JSON库支持这一点吗?org。Json库只是做一个引用比较。
我正在寻找一个JSON解析库,支持比较忽略子顺序的两个JSON对象,特别是用于从web服务返回的单元测试JSON。
有任何主要的JSON库支持这一点吗?org。Json库只是做一个引用比较。
当前回答
这可能会帮助那些使用Spring Framework的人。你可以重用内部使用的在ResultActions上做断言(用于控制器测试):
进口:org.springframework.test.util.JsonExpectationsHelper
你可以编写带有详细输出的测试:
java.lang.AssertionError: someObject.someArray[1].someInternalObject2.value
Expected: 456
got: 4567
测试代码:
@Test
void test() throws Exception {
final String json1 =
"{" +
" 'someObject': {" +
" 'someArray': [" +
" {" +
" 'someInternalObject': {" +
" 'value': '123'" +
" }" +
" }," +
" {" +
" 'someInternalObject2': {" +
" 'value': '456'" +
" }" +
" }" +
" ]" +
" }" +
"}";
final String json2 =
"{" +
" 'someObject': {" +
" 'someArray': [" +
" {" +
" 'someInternalObject': {" +
" 'value': '123'" +
" }" +
" }," +
" {" +
" 'someInternalObject2': {" +
" 'value': '4567'" +
" }" +
" }" +
" ]" +
" }" +
"}";
new JsonExpectationsHelper().assertJsonEqual(json1, json2, true);
}
其他回答
你可以尝试使用json-lib的JSONAssert类:
JSONAssert.assertEquals(
"{foo: 'bar', baz: 'qux'}",
JSONObject.fromObject("{foo: 'bar', baz: 'xyzzy'}")
);
给:
junit.framework.ComparisonFailure: objects differed at key [baz]; expected:<[qux]> but was:<[xyzzy]>
使用GSON
JsonParser parser = new JsonParser();
JsonElement o1 = parser.parse("{a : {a : 2}, b : 2}");
JsonElement o2 = parser.parse("{b : 2, a : {a : 2}}");
assertEquals(o1, o2);
编辑:自GSON v2.8.6起,实例方法JsonParser。不建议使用Parse。你必须使用静态方法JsonParser.parseString:
JsonElement o1 = JsonParser.parseString("{a : {a : 2}, b : 2}");
JsonElement o2 = JsonParser.parseString("{b : 2, a : {a : 2}}");
assertEquals(o1, o2);
其他方法似乎都不太合适,所以我写下了这个:
private boolean jsonEquals(JsonNode actualJson, JsonNode expectJson) {
if(actualJson.getNodeType() != expectJson.getNodeType()) return false;
switch(expectJson.getNodeType()) {
case NUMBER:
return actualJson.asDouble() == expectJson.asDouble();
case STRING:
case BOOLEAN:
return actualJson.asText().equals(expectJson.asText());
case OBJECT:
if(actualJson.size() != expectJson.size()) return false;
Iterator<String> fieldIterator = actualJson.fieldNames();
while(fieldIterator.hasNext()) {
String fieldName = fieldIterator.next();
if(!jsonEquals(actualJson.get(fieldName), expectJson.get(fieldName))) {
return false;
}
}
break;
case ARRAY:
if(actualJson.size() != expectJson.size()) return false;
List<JsonNode> remaining = new ArrayList<>();
expectJson.forEach(remaining::add);
// O(N^2)
for(int i=0; i < actualJson.size(); ++i) {
boolean oneEquals = false;
for(int j=0; j < remaining.size(); ++j) {
if(jsonEquals(actualJson.get(i), remaining.get(j))) {
oneEquals = true;
remaining.remove(j);
break;
}
}
if(!oneEquals) return false;
}
break;
default:
throw new IllegalStateException();
}
return true;
}
您可以尝试JsonUnit。它可以比较两个JSON对象并报告差异。它建在杰克逊的顶部。
例如
assertThatJson("{\"test\":1}").isEqualTo("{\n\"test\": 2\n}");
结果
java.lang.AssertionError: JSON documents are different:
Different value found in node "test". Expected 1, got 2.
ModelAssert - https://github.com/webcompere/model-assert可以做到这一点。默认情况下,它更喜欢JSON是有序的,但它可以使用对象键和数组元素的宽松顺序:
assertJson(json1)
.where().keysInAnyOrder().arrayInAnyOrder()
.isEqualTo(json2);
这个断言是AssertJ风格的——即使用流畅的DSL。ModelAssert还可以用于使用相同的DSL构建Hamcrest或Mockito匹配器。
Json可以是字符串、文件、Jackson JsonNode,甚至是自发转换为Json进行比较的POJO。
还支持yml。