以Map
s 读取JSON文档并进行比较
您可以将JSON文档都读为
Map<K,V>。请参阅以下有关Jackson和Gson的示例:
ObjectMapper mapper = new ObjectMapper();TypeReference<HashMap<String, Object>> type = new TypeReference<HashMap<String, Object>>() {};Map<String, Object> leftMap = mapper.readValue(leftJson, type);Map<String, Object> rightMap = mapper.readValue(rightJson, type);Gson gson = new Gson();Type type = new TypeToken<Map<String, Object>>(){}.getType();Map<String, Object> leftMap = gson.fromJson(leftJson, type);Map<String, Object> rightMap = gson.fromJson(rightJson, type);然后使用番石榴
Maps.difference(Map<K, V>, Map<K,V>)来比较它们。它返回一个
MapDifference<K,V>实例:
MapDifference<String, Object> difference = Maps.difference(leftMap, rightMap);
如果您对结果不满意,可以考虑展 平 地图,然后进行比较。它将提供更好的比较结果,尤其是对于嵌套对象和数组。
创建Flat Map
进行比较
要平整地图,可以使用:
public final class FlatMapUtil { private FlatMapUtil() { throw new AssertionError("No instances for you!"); } public static Map<String, Object> flatten(Map<String, Object> map) { return map.entrySet().stream() .flatMap(FlatMapUtil::flatten) .collect(linkedHashMap::new, (m, e) -> m.put("/" + e.getKey(), e.getValue()), linkedHashMap::putAll); } private static Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entry) { if (entry == null) { return Stream.empty(); } if (entry.getValue() instanceof Map<?, ?>) { return ((Map<?, ?>) entry.getValue()).entrySet().stream() .flatMap(e -> flatten(new AbstractMap.SimpleEntry<>(entry.getKey() + "/" + e.getKey(), e.getValue()))); } if (entry.getValue() instanceof List<?>) { List<?> list = (List<?>) entry.getValue(); return IntStream.range(0, list.size()) .mapToObj(i -> new AbstractMap.SimpleEntry<String, Object>(entry.getKey() + "/" + i, list.get(i))) .flatMap(FlatMapUtil::flatten); } return Stream.of(entry); }}它对密钥使用RFC 6901中定义的 JSON指针符号
,因此您可以轻松地找到值。
例
考虑以下JSON文档:
{ "name": { "first": "John", "last": "Doe" }, "address": null, "birthday": "1980-01-01", "company": "Acme", "occupation": "Software engineer", "phones": [ { "number": "000000000", "type": "home" }, { "number": "999999999", "type": "mobile" } ]}{ "name": { "first": "Jane", "last": "Doe", "nickname": "Jenny" }, "birthday": "1990-01-01", "occupation": null, "phones": [ { "number": "111111111", "type": "mobile" } ], "favorite": true, "groups": [ "close-friends", "gym" ]}和以下代码进行比较并显示差异:
Map<String, Object> leftFlatMap = FlatMapUtil.flatten(leftMap);Map<String, Object> rightFlatMap = FlatMapUtil.flatten(rightMap);MapDifference<String, Object> difference = Maps.difference(leftFlatMap, rightFlatMap);System.out.println("Entries only on the leftn--------------------------");difference.entriesOnlyOnLeft() .forEach((key, value) -> System.out.println(key + ": " + value));System.out.println("nnEntries only on the rightn--------------------------");difference.entriesOnlyOnRight() .forEach((key, value) -> System.out.println(key + ": " + value));System.out.println("nnEntries differingn--------------------------");difference.entriesDiffering() .forEach((key, value) -> System.out.println(key + ": " + value));它将产生以下输出:
Entries only on the left--------------------------/address: null/phones/1/number: 999999999/phones/1/type: mobile/company: AcmeEntries only on the right--------------------------/name/nickname: Jenny/groups/0: close-friends/groups/1: gym/favorite: trueEntries differing--------------------------/birthday: (1980-01-01, 1990-01-01)/occupation: (Software engineer, null)/name/first: (John, Jane)/phones/0/number: (000000000, 111111111)/phones/0/type: (home, mobile)



