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

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


当前回答

org。我已经推出了自己的解决方案,一个与JSONObject实例进行比较的方法。我在那个项目中没有使用复杂的JSON对象,所以我不知道这是否适用于所有场景。此外,鉴于我在单元测试中使用了这个功能,我没有在优化方面投入精力。下面就是:

public static boolean jsonObjsAreEqual (JSONObject js1, JSONObject js2) throws JSONException {
    if (js1 == null || js2 == null) {
        return (js1 == js2);
    }

    List<String> l1 =  Arrays.asList(JSONObject.getNames(js1));
    Collections.sort(l1);
    List<String> l2 =  Arrays.asList(JSONObject.getNames(js2));
    Collections.sort(l2);
    if (!l1.equals(l2)) {
        return false;
    }
    for (String key : l1) {
        Object val1 = js1.get(key);
        Object val2 = js2.get(key);
        if (val1 instanceof JSONObject) {
            if (!(val2 instanceof JSONObject)) {
                return false;
            }
            if (!jsonObjsAreEqual((JSONObject)val1, (JSONObject)val2)) {
                return false;
            }
        }

        if (val1 == null) {
            if (val2 != null) {
                return false;
            }
        }  else if (!val1.equals(val2)) {
            return false;
        }
    }
    return true;
}

其他回答

我所做的是使用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);

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

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

我做的一件事是将两个对象读入HashMap,然后与常规的assertEquals()进行比较。它将调用哈希映射的equals()方法,该方法将递归地比较其中的所有对象(它们将是其他哈希映射或一些单值对象,如字符串或整数)。这是使用Codehaus的Jackson JSON解析器完成的。

assertEquals(mapper.readValue(expectedJson, new TypeReference<HashMap<String, Object>>(){}), mapper.readValue(actualJson, new TypeReference<HashMap<String, Object>>(){}));

如果JSON对象是一个数组,则可以使用类似的方法。

你可以尝试使用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]>

作为一个通用的架构点,我通常建议不要让对特定序列化格式的依赖超出您的存储/网络层;因此,我首先建议您考虑测试您自己的应用程序对象之间的相等性,而不是它们的JSON表示。

话已这么说,我目前是Jackson的忠实粉丝,我快速阅读了他们的ObjectNode.equals()实现,建议进行你想要的集合成员比较:

public boolean equals(Object o)
{
    if (o == this) return true;
    if (o == null) return false;
    if (o.getClass() != getClass()) {
        return false;
    }
    ObjectNode other = (ObjectNode) o;
    if (other.size() != size()) {
        return false;
    }
    if (_children != null) {
        for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
            String key = en.getKey();
            JsonNode value = en.getValue();

            JsonNode otherValue = other.get(key);

            if (otherValue == null || !otherValue.equals(value)) {
                return false;
            }
        }
    }
    return true;
}