【问题标题】:Testing two JSON objects for equality ignoring child order in Java [closed]在Java中测试两个JSON对象的相等性忽略子顺序[关闭]
【发布时间】:2011-01-16 06:15:33
【问题描述】:

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

任何主要的 JSON 库都支持这个吗? org.json 库只是做一个参考比较。

【问题讨论】:

  • 无法将两个对象序列化为字符串表示并进行比较?我猜所有的库都支持toString() 将对象转换为JSON 字符串。
  • 假设序列化到和从字符串的顺序总是相同的。我不愿意做出这样的假设。
  • 你说得对,杰夫,这根本不安全。此测试显示了映射相同但 toString() 不返回相同输出的场景:gist.github.com/anonymous/5974797。这是因为底层的 HashMap 是可以增长的,如果去掉 key,HashMap 内部数组不会缩小。
  • Json 比较 json-compare

标签: java json junit


【解决方案1】:

我将使用http://json.org/java/ 的库,并修改JSONObject 和JSONArray 的equals 方法以进行深度相等性测试。为了确保它的工作不受孩子的顺序影响,您需要做的就是用TreeMap 替换内部地图,或者使用Collections.sort() 之类的东西。

【讨论】:

  • 它不是很好 - 它确实应该带有代码来进行 json 比较。
  • 但是想象一下,在 JSON 可以是任何结构的任何东西的情况下编写代码......在上面写下比较!这就像为所有类型的 HTML 页面编写一个比较。
【解决方案2】:

作为一般架构点,我通常建议不要让对特定序列化格式的依赖超出您的存储/网络层;因此,我首先建议您考虑测试您自己的应用程序对象之间的相等性,而不是它们的 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;
}

【讨论】:

  • 这个方法不是对称的,因为它只测试孩子的“子集”关系,而不是平等。 'other' 对象可能比 _children 有更多的子对象,并且此方法仍会返回 true。
  • @Yoni:不正确,因为有大小比较。他们必须有完全相同数量的孩子以及相同的孩子。 @Jolly Roger:在这种情况下,我不会将对象从 JSON 序列化回 POJO,但是当发送 JSON 系统时,我不能依赖它以与我发送时完全相同的格式将其发送回它。
  • @Jeff 这对你有用吗?在junit中, assertEquals 对我来说失败了。该项目使用的是旧版本 (1.5),仅供参考。
  • 如果您不断言 JSON,我认为您错过了一些高级测试。您可以进行一个瘦测试,它发出一个 http 请求并以一些预期的 JSON 响应 - 这是 Web 服务的主要功能行为。
  • 关于性能的一点小提示:比较 'value' 和 'otherValue' 的代码可以简化为 if (value.equals(other.get(key)) return false; as 'value'保证不为空,并且 JsonNode 的 equals() 方法应该接受一个空参数。
【解决方案3】:

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

【讨论】:

  • 或者更简单:JSONAssert.assertJsonEquals("{foo: 'bar', baz: 'qux'}", {foo: 'bar', baz: 'xyzzy'}");跨度>
  • 虽然此解决方案适用于 JSON 中数据项的顺序,但如果数组中元素的顺序不匹配,它将失败。例如,如果您的代码使用转换为 JSON 的 Set。以下 JSON 比较将失败:JSONAssert.assertJsonEquals( "{foo: 'bar', list: [{test: '1'}, {rest: '2'}] }", "{ foo: 'bar', list: [{rest: '2'}, {test: '1'}] }"); 带有消息:junit.framework.AssertionFailedError: : : objects differed at key [list];: arrays first differed at element [0];: objects differed at key [test];
  • 是的,这是Json的一个限制:(。json.org显示没有无序的集合token。{}只能包围键值对。这很烦人
【解决方案4】:

我做了一件事并且效果很好,就是将两个对象都读入 HashMap,然后与常规的 assertEquals() 进行比较。它将调用 hashmap 的 equals() 方法,该方法将递归地比较内部的所有对象(它们将是其他 hashmap 或一些单值对象,如字符串或整数)。这是使用 Codehaus 的 Jackson JSON 解析器完成的。

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

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

【讨论】:

    【解决方案5】:

    使用 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);
    

    【讨论】:

    • 为我在 GSON 2.8.2 中工作。
    • 如果 jsonArray 元素不按顺序排列,则无法正常工作。 2.8.2版
    • 如果对象/元素的顺序不同,则不适合我
    • 它对我有用,因为我只是希望它用于两个 jsons 属性具有相同顺序的单元测试
    • @GabrielBB 您应该编辑问题并指出 API 已被弃用的版本,以及新的代码样式在哪个版本中开始工作。
    【解决方案6】:

    你可以试试JsonUnit。它可以比较两个 JSON 对象并报告差异。它建立在 Jackson 之上。

    例如

    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.
    

    【讨论】:

      【解决方案7】:

      试试 Skyscreamer 的JSONAssert

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

      • 对象可扩展性(例如,对于 {id:1} 的预期值,这仍然会通过:{id:1,moredata:'x'}。)
      • 松散的数组排序(例如 ['dog','cat']==['cat','dog'])

      在严格模式下,它的行为更像 json-lib 的测试类。

      测试看起来像这样:

      @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() 调用中的参数是expectedJSONStringactualDataStringisStrict

      结果消息非常清晰,这在比较非常大的 JSON 对象时很重要。

      【讨论】:

      • 我一直在使用这个解决方案,但我刚刚发现您也可以提供您选择的 JSONCompareMode。其中之一是 NON_EXTENSIBLE。所以你会有这样的东西:JSONAssert.assertEquals(expected, data, JSONCompareMode.NON_EXTENSIBLE); NON_EXTENSIBLE 模式意味着任何新的或缺失的字段都会导致失败,但订单不会。使用 false 将启动宽松模式,该模式不会报告任何额外或缺失的子元素。
      • NON_EXTENSIBLE 比较模式正是我正在寻找的。谢谢你,丹。
      • 在我兴奋之前:这是否也支持嵌套的 JSON 对象和数组? :)
      • 人们可能希望在使用库之前考虑this JSONassert issue:这表明当前存在与库的依赖相关的潜在许可问题。
      • JSONAssert 问题 #44 修复了 PR 67 中的洁净室库替换,今天作为 JSONAssert 1.4.0 发布。
      【解决方案8】:

      对于 org.json,我推出了自己的解决方案,一种与 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;
      }
      

      【讨论】:

      • 既然你提到了优化 :),如果val1 为空,你会从这段代码if (!val1.equals(val2)) { 得到一个 NullPointerException
      • 这也发生在我们最好的人身上:)。 +1 在您的答案中修复它。
      • 点了 :) 希望它不会得到太多的选票,否则会得到很多支持。
      • js1不是null时,你没有考虑js2是否是null
      • 此代码不适用于嵌套对象/序列。
      【解决方案9】:

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

      有一个名为hamcrest-json 的小型开源库,具有可识别JSON 的匹配。它有很好的文档记录、测试和支持。以下是一些有用的链接:

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

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

      或者,您可以 (1) 允许“任意顺序”数组并 (2) 忽略额外字段。

      由于 Java 有多种 JSON 库(JacksonGSONjson-lib 等),因此hamcrest-json 支持 JSON 文本(如 java.lang.String)以及原生支持来自 Douglas Crockford 的 JSON 库 org.json 的对象。

      最后,如果你不使用 JUnit,你可以直接使用 Hamcrest 进行断言。 (I wrote about it here.)

      【讨论】:

      • 使用hamcrast匹配器而不是直接使用JSONAssert有什么好处?
      • @Johannes:仅样式。
      • hamcrest-json 源当前的最后提交日期为 2012 年。它可能不再得到很好的支持。
      【解决方案10】:

      试试这个:

      public static boolean jsonsEqual(Object obj1, Object obj2) throws JSONException
      
          {
              if (!obj1.getClass().equals(obj2.getClass()))
              {
                  return false;
              }
      
              if (obj1 instanceof JSONObject)
              {
                  JSONObject jsonObj1 = (JSONObject) obj1;
      
                  JSONObject jsonObj2 = (JSONObject) obj2;
      
                  String[] names = JSONObject.getNames(jsonObj1);
                  String[] names2 = JSONObject.getNames(jsonObj1);
                  if (names.length != names2.length)
                  {
                      return false;
                  }
      
                  for (String fieldName:names)
                  {
                      Object obj1FieldValue = jsonObj1.get(fieldName);
      
                      Object obj2FieldValue = jsonObj2.get(fieldName);
      
                      if (!jsonsEqual(obj1FieldValue, obj2FieldValue))
                      {
                          return false;
                      }
                  }
              }
              else if (obj1 instanceof JSONArray)
              {
                  JSONArray obj1Array = (JSONArray) obj1;
                  JSONArray obj2Array = (JSONArray) obj2;
      
                  if (obj1Array.length() != obj2Array.length())
                  {
                      return false;
                  }
      
                  for (int i = 0; i < obj1Array.length(); i++)
                  {
                      boolean matchFound = false;
      
                      for (int j = 0; j < obj2Array.length(); j++)
                      {
                          if (jsonsEqual(obj1Array.get(i), obj2Array.get(j)))
                          {
                              matchFound = true;
                              break;
                          }
                      }
      
                      if (!matchFound)
                      {
                          return false;
                      }
                  }
              }
              else
              {
                  if (!obj1.equals(obj2))
                  {
                      return false;
                  }
              }
      
              return true;
          }
      

      【讨论】:

      • 在 jsonArrays 中,如果 一些 元素重合,而不是 所有 元素重合,则返回 true。
      • @matiasg - if (obj1Array.length() != obj2Array.length()) 不能确保 所有 元素一致吗?
      • @kwah:不。考虑这个例子:obj1Array = [1,1,1],obj2Array = [1,2,3]。这将返回 true。此外,即使元素重合,它们也应该是相同的顺序。这对于 [1,2,3] 和 [2,3,1] 也会返回 true,这是错误的
      【解决方案11】:

      我会做以下事情,

      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);
      

      【讨论】:

      • 如果您已经在使用 Jackson,恕我直言,这是最好的答案。
      • 但我认为这是一个严格的比较。对于具有不同元素顺序的两个相等的 json,它将返回 false。
      • @deadpool,以前可能是严格比较,现在不严格了。
      • 当您将数组作为嵌套对象并且数组中的顺序存在差异时,这不起作用
      • 这将忽略大多数订单更改,除了必须相同的列表订单更改。看这里:baeldung.com/jackson-compare-two-json-objects
      【解决方案12】:

      对于像我这样想与杰克逊一起做这件事的人,你可以使用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.
      

      【讨论】:

        【解决方案13】:

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

        【讨论】:

        • 您能否添加更多评论我们如何使用它我将它添加到我的 pom 但我们需要文档才能了解如何使用它
        • 肯定用法很简单:把这个添加到你的 pom.xml 中。 net.javacrumbs.json-unitjson-unit1.5.0test
        • 10x 我查看了链接上的说明并找到了它:)
        【解决方案14】:

        您可以使用zjsonpatch 库,它根据 RFC 6902 (JSON Patch) 呈现差异信息。它非常易于使用。请访问其说明页面了解其用法

        【讨论】:

          【解决方案15】:

          我正在使用它,并且对我来说效果很好(使用 org.json.*):

          package com.project1.helpers;
          
          import org.json.JSONArray;
          import org.json.JSONException;
          import org.json.JSONObject;
          
          import java.util.HashMap;
          import java.util.HashSet;
          import java.util.Iterator;
          import java.util.Map;
          import java.util.Set;
          
          public class JSONUtils {
          
              public static boolean areEqual(Object ob1, Object ob2) throws JSONException {
                  Object obj1Converted = convertJsonElement(ob1);
                  Object obj2Converted = convertJsonElement(ob2);
                  return obj1Converted.equals(obj2Converted);
              }
          
              private static Object convertJsonElement(Object elem) throws JSONException {
                  if (elem instanceof JSONObject) {
                      JSONObject obj = (JSONObject) elem;
                      Iterator<String> keys = obj.keys();
                      Map<String, Object> jsonMap = new HashMap<>();
                      while (keys.hasNext()) {
                          String key = keys.next();
                          jsonMap.put(key, convertJsonElement(obj.get(key)));
                      }
                      return jsonMap;
                  } else if (elem instanceof JSONArray) {
                      JSONArray arr = (JSONArray) elem;
                      Set<Object> jsonSet = new HashSet<>();
                      for (int i = 0; i < arr.length(); i++) {
                          jsonSet.add(convertJsonElement(arr.get(i)));
                      }
                      return jsonSet;
                  } else {
                      return elem;
                  }
              }
          }
          

          【讨论】:

            【解决方案16】:

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

            Hamcrest JSON SameJSONAs

            【讨论】:

              【解决方案17】:

              Karate 正是您要找的。这是一个例子:

              * def myJson = { foo: 'world', hey: 'ho', zee: [5], cat: { name: 'Billie' } }
              * match myJson = { cat: { name: 'Billie' }, hey: 'ho', foo: 'world', zee: [5] }
              

              (免责声明:此处为开发人员)

              【讨论】:

                【解决方案18】:

                似乎没有其他方法可以正常工作,所以我写了这个:

                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;
                }
                

                【讨论】:

                  【解决方案19】:

                  以下代码将有助于比较两个 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;
                      }
                  

                  【讨论】:

                    【解决方案20】:

                    为了比较 json,我建议使用我的库 JSONCompare: https://github.com/fslev/json-compare

                    // Compare by regex
                    String expected = "{\"a\":\".*me.*\"}";
                    String actual = "{\"a\":\"some text\"}";
                    JSONCompare.assertEquals(expected, actual);  // True
                    
                    // Check expected array has no extra elements
                    String expected = "[1,\"test\",4,\"!.*\"]";
                    String actual = "[4,1,\"test\"]";
                    JSONCompare.assertEquals(expected, actual);  // True
                    
                    // Check expected array has no numbers
                    String expected = "[\"\\\\\\d+\"]";
                    String actual = "[\"text\",\"test\"]";
                    JSONCompare.assertEquals(expected, actual);  // True
                    
                    // Check expected array has no numbers
                    String expected = "[\"\\\\\\d+\"]";
                    String actual = "[2018]";
                    JSONCompare.assertNotEquals(expected, actual);  // True
                    

                    【讨论】:

                      【解决方案21】:
                      JSON.areEqual(json1, json2); //using BlobCity Java Commons
                      

                      https://tech.blobcity.com/2018/09/02/json-equals-in-java-to-compare-two-jsons

                      【讨论】:

                        【解决方案22】:

                        查看答案,我尝试了 JSONAssert 但失败了。所以我将 Jackson 与 zjsonpatch 一起使用。我在 SO 答案 here 中发布了详细信息。

                        【讨论】:

                          【解决方案23】:

                          JSONObject 中的toMap() 已经可以很好地处理嵌套对象和数组。

                          由于 java.util.Map 接口指定检查映射而不是顺序,因此比较 Map 很好,而且是递归的。

                          json1 = new JSONObject("{...}");
                          json2 = new JSONObject("{...}");
                          json1.toMap().equals(json2.toMap());
                          

                          它适用于任何顺序和嵌套元素。

                          它会但是适用于额外/忽略的元素。如果这些是已知的,您可以在地图上调用 equals 之前将其删除。

                          【讨论】:

                            【解决方案24】:

                            任何主要的 JSON 库都支持这个吗? org.json 库只是做一个参考比较。

                            但是org.json确实支持这个!使用similar() 而不是equals()

                            【讨论】:

                              【解决方案25】:

                              我所做的是使用 gson 将 json 转换为地图并使用 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);
                              

                              结果是所有属性之间的一个很好的递归比较!!!

                              【讨论】:

                                【解决方案26】:

                                这是使用 Jackson ObjectMapper 的代码。要了解更多信息,请阅读this article

                                import com.fasterxml.jackson.*
                                
                                boolean compareJsonPojo(Object pojo1, Object pojo2) {
                                        try {
                                            ObjectMapper mapper = new ObjectMapper();
                                            String str1 = mapper.writeValueAsString(pojo1);
                                            String str2 = mapper.writeValueAsString(pojo2);
                                            return mapper.readTree(str1).equals(mapper.readTree(str2));
                                        } catch (JsonProcessingException e) {
                                            throw new AssertionError("Error comparing JSON objects: " + e.getMessage());
                                        }
                                    }
                                

                                【讨论】:

                                  【解决方案27】:

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

                                  【讨论】:

                                    【解决方案28】:

                                    ModelAssert - https://github.com/webcompere/model-assert 执行此操作。默认情况下,它更喜欢 JSON 有序,但它可以使用对象键和数组元素的宽松顺序:

                                    assertJson(json1)
                                       .where().keysInAnyOrder().arrayInAnyOrder()
                                       .isEqualTo(json2);
                                    

                                    这个断言是 AssertJ 风格 - 即使用流利的 DSL。 ModelAssert 也可用于构建具有相同 DSL 的 Hamcrest 或 Mockito 匹配器。

                                    Json 可以是 StringFile、Jackson JsonNode,甚至是自发转换为 JSON 以进行比较的 POJO。

                                    还有对 yml 的支持。

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2019-05-08
                                      相关资源
                                      最近更新 更多