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

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


当前回答

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

其他回答

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

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

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

我知道它通常只用于测试,但你可以使用Hamcrest JSON中的comparitorSameJSONAs。

Hamcrest JSON SameJSONAs

使用这个库: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]}");

这可能会帮助那些使用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);
}

对于像我这样想要使用Jackson的人,您可以使用json-unit。

JsonAssert.assertJsonEquals(jsonNode1, jsonNode2);

错误给出了关于不匹配类型的有用反馈:

java.lang.AssertionError: JSON documents have different values:
Different value found in node "heading.content[0].tag[0]". Expected 10209, got 10206.