我正在寻找一个JSON解析库,支持比较忽略子顺序的两个JSON对象,特别是用于从web服务返回的单元测试JSON。

有任何主要的JSON库支持这一点吗?org。Json库只是做一个引用比较。


当前回答

您可以使用zjsonpatch库,它根据RFC 6902 (JSON Patch)显示差异信息。它很容易使用。请访问其说明页面了解其用法

其他回答

如果您已经在使用JUnit,那么最新版本现在使用Hamcrest。它是一个通用的匹配框架(对单元测试特别有用),可以扩展以构建新的匹配器。

有一个名为hamcrest-json的小型开源库,它具有json感知匹配。它有良好的文档、测试和支持。以下是一些有用的链接:

源代码 主页 主匹配器的Javadocs:

使用JSON库org.json.simple对象的示例代码:

Assert.assertThat(
    jsonObject1.toJSONString(),
    SameJSONAs.sameJSONAs(jsonObject2.toJSONString()));

可选地,您可以(1)允许“任意顺序”数组和(2)忽略额外的字段。

由于Java有多种JSON库(Jackson, GSON, JSON -lib等),hamcrest-json支持JSON文本(如Java .lang. string),以及原生支持来自Douglas Crockford的JSON库org.json的对象是很有用的。

最后,如果不使用JUnit,可以直接使用Hamcrest进行断言。(我在这里写过。)

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。

下面的代码将更有助于比较两个JsonObject, JsonArray, JsonPrimitive和JasonElements。

private boolean compareJson(JsonElement json1, JsonElement json2) {
        boolean isEqual = true;
        // Check whether both jsonElement are not null
        if (json1 != null && json2 != null) {

            // Check whether both jsonElement are objects
            if (json1.isJsonObject() && json2.isJsonObject()) {
                Set<Entry<String, JsonElement>> ens1 = ((JsonObject) json1).entrySet();
                Set<Entry<String, JsonElement>> ens2 = ((JsonObject) json2).entrySet();
                JsonObject json2obj = (JsonObject) json2;
                if (ens1 != null && ens2 != null) {
                    // (ens2.size() == ens1.size())
                    // Iterate JSON Elements with Key values
                    for (Entry<String, JsonElement> en : ens1) {
                        isEqual = isEqual && compareJson(en.getValue(), json2obj.get(en.getKey()));
                    }
                } else {
                    return false;
                }
            }

            // Check whether both jsonElement are arrays
            else if (json1.isJsonArray() && json2.isJsonArray()) {
                JsonArray jarr1 = json1.getAsJsonArray();
                JsonArray jarr2 = json2.getAsJsonArray();
                if (jarr1.size() != jarr2.size()) {
                    return false;
                } else {
                    int i = 0;
                    // Iterate JSON Array to JSON Elements
                    for (JsonElement je : jarr1) {
                        isEqual = isEqual && compareJson(je, jarr2.get(i));
                        i++;
                    }
                }
            }

            // Check whether both jsonElement are null
            else if (json1.isJsonNull() && json2.isJsonNull()) {
                return true;
            }

            // Check whether both jsonElement are primitives
            else if (json1.isJsonPrimitive() && json2.isJsonPrimitive()) {
                if (json1.equals(json2)) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } else if (json1 == null && json2 == null) {
            return true;
        } else {
            return false;
        }
        return isEqual;
    }

我所做的是使用gson将jsons转换为map,并使用assertj比较这些映射:

Map<Object, Object> resMap = gson.fromJson(res, new TypeToken<Map<Object, Object>>() {}.getType());
Map<Object, Object> expectedMap = gson.fromJson(expected, new TypeToken<Map<Object, Object>>() {}.getType());
Assertions.assertThat(resMap).usingRecursiveComparison().isEqualTo(expectedMap);

结果是递归地比较了所有属性!!

我将使用http://json.org/java/上的库,并修改JSONObject和JSONArray的equals方法来进行深入的相等性测试。为了确保它可以不分子元素的顺序重新排序,您所需要做的就是用TreeMap替换内部映射,或者使用Collections.sort()之类的东西。