在比较两个JSON时忽略特定节点/属性

我想比较两个JSON字符串,这是一个巨大的层次结构,并想知道它们在值上的不同之处。 但是某些值是在运行时生成的并且是动态的。 我想忽略我比较中的那些特定节点。

我目前正在使用org.SkyScreamer的JSONAssert进行比较。 它给了我很好的控制台输出但不忽略任何属性。

对于前

java.lang.AssertionError messageHeader.sentTime expected:null got:09082016 18:49:41.123 

现在这是动态的,应该被忽略。 就像是

 JSONAssert.assertEquals(expectedJSONString, actualJSONString,JSONCompareMode, *list of attributes to be ignored*) 

如果有人在JSONAssert中建议解决方案,那就太好了。 然而,其他方式也是受欢迎的。

您可以使用自定义。 例如,如果您需要忽略名为“timestamp”的顶级属性,请使用:

 JSONAssert.assertEquals(expectedResponseBody, responseBody, new CustomComparator(JSONCompareMode.LENIENT, new Customization("timestamp", (o1, o2) -> true))); 

也可以使用像“entry.id”这样的路径表达式。 在您的自定义中,您可以使用您喜欢的任何方法来比较这两个值。 无论期望值和实际值是什么,上面的示例始终返回true。 如果需要,你可以在那里做更复杂的事情。

首先,它存在未解决的问题 。

在我的测试中,我将json从控制器与实际对象进行比较,并在JsonUtil类的帮助下进行序列化/反序列化:

 public class JsonUtil { public static  List readValues(String json, Class clazz) { ObjectReader reader = getMapper().readerFor(clazz); try { return reader.readValues(json).readAll(); } catch (IOException e) { throw new IllegalArgumentException("Invalid read array from JSON:\n'" + json + "'", e); } } public static  T readValue(String json, Class clazz) { try { return getMapper().readValue(json, clazz); } catch (IOException e) { throw new IllegalArgumentException("Invalid read from JSON:\n'" + json + "'", e); } } public static  String writeValue(T obj) { try { return getMapper().writeValueAsString(obj); } catch (JsonProcessingException e) { throw new IllegalStateException("Invalid write to JSON:\n'" + obj + "'", e); } } 

要忽略特定的对象字段,我添加了新方法:

 public static  String writeIgnoreProps(T obj, String... ignoreProps) { try { Map map = getMapper().convertValue(obj, new TypeReference>() {}); for (String prop : ignoreProps) { map.remove(prop); } return getMapper().writeValueAsString(map); } catch (JsonProcessingException e) { throw new IllegalStateException("Invalid write to JSON:\n'" + obj + "'", e); } } 

而我在测试中的断言现在看起来像这样:

  mockMvc.perform(get(REST_URL)) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andExpect(content().json(JsonUtil.writeIgnoreProps(USER, "registered"))) 

您可以使用JsonUnit它具有您正在寻找的function,我们可以忽略空的字段,路径和值等。请查看更多信息。 至于示例,您可以忽略这样的路径

 assertJsonEquals( "{\"root\":{\"test\":1, \"ignored\": 2}}", "{\"root\":{\"test\":1, \"ignored\": 1}}", whenIgnoringPaths("root.ignored") ); 

有时您需要在比较时忽略某些值。 可以像这样使用$ {json-unit.ignore}占位符

 assertJsonEquals("{\"test\":\"${json-unit.ignore}\"}", "{\n\"test\": {\"object\" : {\"another\" : 1}}}");