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

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


当前回答

我会这么做,

JSONObject obj1 = /*json*/;
JSONObject obj2 = /*json*/;

ObjectMapper mapper = new ObjectMapper();

JsonNode tree1 = mapper.readTree(obj1.toString());
JsonNode tree2 = mapper.readTree(obj2.toString());

return tree1.equals(tree2);

其他回答

使用这个库:https://github.com/lukas-krecan/JsonUnit

Pom:

<dependency>
    <groupId>net.javacrumbs.json-unit</groupId>
    <artifactId>json-unit-assertj</artifactId>
    <version>2.24.0</version>
    <scope>test</scope>
</dependency>

IGNORING_ARRAY_ORDER -忽略数组中的顺序

assertThatJson("{\"test\":[1,2,3]}")
  .when(Option.IGNORING_ARRAY_ORDER)
  .isEqualTo("{\"test\": [3,2,1]}");

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

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

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

试试天空尖叫者的圣像。

它的非严格模式有两个主要优点,使其不那么脆弱:

对象的可扩展性(例如,期望值为{id:1},仍然会通过:{id:1,moredata:'x'}。) 宽松的数组排序(例如[‘狗’,‘猫’]= =[“猫”,“狗”])

在严格模式下,它更像json-lib的test类。

测试是这样的:

@Test
public void testGetFriends() {
    JSONObject data = getRESTData("/friends/367.json");
    String expected = "{friends:[{id:123,name:\"Corby Page\"}"
        + ",{id:456,name:\"Solomon Duskis\"}]}";
    JSONAssert.assertEquals(expected, data, false);
}

JSONAssert.assertEquals()调用中的参数是expectedJSONString, actualDataString和isStrict。

结果消息非常清晰,这在比较非常大的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;
}

如果您已经在使用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进行断言。(我在这里写过。)