java — Сравнить два объекта json с одинаковыми ключами в разном порядке

#java

#java

Вопрос:

Дано два объекта json

 String a1 = "{"a":[{"b":"1"}, {"b":"2"}]}";
String a2 = "{"a":[{"b":"2"}, {"b":"1"}]}";
  

Я хотел бы сравнить их независимо от порядка объектов в массиве. Я использую Jackson , но это не работает.

 ObjectMapper om = new ObjectMapper().configure(
    SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true
);
Map<String, Object> m1 = (Map<String, Object>)(om.readValue(a1, Map.class));
Map<String, Object> m2 = (Map<String, Object>)(om.readValue(a2, Map.class));
System.out.println(m1.equals(m2));
  

Есть ли какой-нибудь удобный способ их правильного сравнения?

Комментарии:

1. Они не равны.

2. почему вы считаете, что эти объекты равны?

3. Моя ошибка. Я бы скорее сказал, сравнивая их независимо от порядка объектов в массиве.

Ответ №1:

Ваш om.readValue() вызов возвращает Map<String, List<Map<String, Integer>>> :

 Map<String, List<Map<String, Integer>>> m1 = om.readValue(a1, Map.class);
Map<String, List<Map<String, Integer>>> m2 = om.readValue(a2, Map.class);

System.out.println(m1); //{a=[{b=1}, {b=2}]}
System.out.println(m2); //{a=[{b=2}, {b=1}]}
  

Списки {b=1}, {b=2} и {b=2}, {b=1} не равны из-за их порядка.
Итак, я преобразовал список в HashSet, а затем запустил сравнение:

 Map<String, HashSet<Map<String, Integer>>> m1Collected = m1.entrySet().stream()
        .map(e -> Map.entry(e.getKey(), new HashSet<>(e.getValue())))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Map<String, HashSet<Map<String, Integer>>> m2Collected = m2.entrySet().stream()
        .map(e -> Map.entry(e.getKey(), new HashSet<>(e.getValue())))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

System.out.println(m1Collected.equals(m2Collected)); //prints true
  

Вы также можете использовать JSONassert со строгим режимом, установленным в false, для сравнения JSON-файлов, игнорируя порядок.

Комментарии:

1. но тогда вы модифицируете объект перед его сравнением. Это все равно, что сказать "foo" == "ofo"

2. @njzk2 если бы OP хотел сравнить порядок, они бы не опубликовали вопрос