Как сравнить две строки JSON, когда порядок записей постоянно меняется

У меня есть строка типа - {"state":1,"cmd":1}, мне нужно сравнить ее с сгенерированным выводом, но в сгенерированном выводе порядок продолжает меняться, т.е. иногда его {"state":1,"cmd":1}, иногда его {"cmd":1,"state":1}.

В настоящее время я использовал метод equals() для сравнения. Что может быть лучше в этом сценарии для проверки двух строк. Меня беспокоит только то, что обе записи присутствуют в строке, порядок не определен.


person Green    schedule 19.05.2015    source источник
comment
Разберите строки, создайте два экземпляра настраиваемого класса и сравните их.   -  person Konstantin Yovkov    schedule 19.05.2015
comment
equals - это не то же самое, что сравнение. Сравнение означает, что существует отношение порядка, тогда как равенство проверяет, проверяется, являются ли два объекта одинаковыми.   -  person Willem Van Onsem    schedule 19.05.2015
comment
Вам нужно будет написать что-то более сложное, например, предложенное @kocko. Разберите строку на предмет того, что вас интересует, и затем сравните.   -  person Juru    schedule 19.05.2015
comment
Обе строки следует рассматривать как равные, даже если порядок отличается? Это то, что вы говорите?   -  person Soumitri Pattnaik    schedule 19.05.2015
comment
@SoumitriPattnaik .... я   -  person Green    schedule 19.05.2015
comment
@Green проверьте мой ответ ниже, у меня это сработало   -  person Soumitri Pattnaik    schedule 19.05.2015
comment
@JarrodRoberson: Я думаю, что это не полный дубликат, поскольку вопрос касается сравнения двух JSON строк. Потенциально другой ответ - это программа, которая выполняет сравнение на строковом уровне без необходимости полного декодирования (и сохранения) обоих объектов в памяти.   -  person Willem Van Onsem    schedule 19.05.2015
comment
объясните, пожалуйста, как можно сравнить JSON, закодированный как строку, без ее анализа? строки не совпадают, если они не проанализированы, просты и понятны, правильный ответ - проанализировать его и сравнить как какой-то объект независимо от того, как и все ответы здесь говорят, это дубликат на практике и по духу.   -  person    schedule 19.05.2015
comment
@JarrodRoberson: для огромных строк, которые вы читаете из файла, вам может быть, например, интересно построить автомат push-down, который перечисляет ключи / значения файла, а затем проверяет, можно ли их найти во втором файле. Если размер вашего файла составляет 20 ГБ +, но размер каждого элемента меньше 100 МБ, его анализ не умещается в памяти, тогда как при обработке текста можно проверить, равны ли объекты. Сравните это с сканированием дубликатов файлов: вы не храните в памяти все файлы на диске (вы не анализируете их), вы вычисляете хеши, а затем сравниваете два файловых потока.   -  person Willem Van Onsem    schedule 19.05.2015
comment
если у вас есть строка в кодировке JSON размером 20 ГБ, у вас есть более серьезные проблемы, с которыми нужно иметь дело, ваш пример не совпадает с примером, заданным в вопросе, совершенно другая проблемная область   -  person    schedule 19.05.2015
comment
Как, например? Это может быть дамп какой-то базы данных. Если дамп SO составляет 60+ ГиБ в XML, почему вместо этого нельзя использовать JSON. Существуют системы запросов XPath (например, синтаксический анализатор SAX) для работы с XML-файлами, которым требуется всего несколько мегабайт памяти для обработки файлов размером 100 ГБ +.   -  person Willem Van Onsem    schedule 19.05.2015


Ответы (4)


Парсер Jackson Json имеет приятную особенность, заключающуюся в том, что он может преобразовывать строку Json в карту. Затем вы можете запросить записи или просто спросить о равенстве:

import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.*;

public class Test
{
    public static void main(String... args)
    {
        String input1 = "{\"state\":1,\"cmd\":1}";
        String input2 = "{\"cmd\":1,\"state\":1}";
        ObjectMapper om = new ObjectMapper();
        try {
            Map<String, Object> m1 = (Map<String, Object>)(om.readValue(input1, Map.class));
            Map<String, Object> m2 = (Map<String, Object>)(om.readValue(input2, Map.class));
            System.out.println(m1);
            System.out.println(m2);
            System.out.println(m1.equals(m2));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

На выходе

{state=1, cmd=1}
{cmd=1, state=1}
true
person Sharon Ben Asher    schedule 19.05.2015
comment
это не применимо в случае списка в полезной нагрузке json - person ; 28.10.2016
comment
это также вызовет Unchecked cast предупреждение - person Ghilteras; 03.07.2019

Вы также можете использовать Gson API

 JsonParser parser = new JsonParser();
 JsonElement o1 = parser.parse("{\"state\":1,\"cmd\":1}");
 JsonElement o2 = parser.parse("{\"cmd\":1,\"state\":1}");
 System.out.println(o1.equals(o2));
person Rockstar    schedule 19.05.2015
comment
Не работает в Gson 1.7.1 - person Dherik; 02.02.2016
comment
работает для Gson 2.2.4 - person nieschumi; 11.10.2016
comment
Если эти два JsonElement не похожи, то можем ли мы выяснить, какие из этих компонентов отличаются? - person drp; 30.11.2016
comment
@drp Эта ветка может помочь: stackoverflow.com/questions/32323256/ - person Rockstar; 01.12.2016

Попробуй это

 import java.util.*;
 import com.google.gson.*;

 public class CompareArray {
   static Set<JsonElement> setOfElements(JsonArray arr) {
      Set<JsonElement> set = new HashSet<JsonElement>();
      for (JsonElement j: arr) {
          set.add(j);
        }
        return set;
    }

    public static void main(String[] args) {
        JsonParser parser = new JsonParser();
        Set<JsonElement> arr1elems =
setOfElements(parser.parse(args[0]).getAsJsonArray());
        Set<JsonElement> arr2elems =
setOfElements(parser.parse(args[1]).getAsJsonArray());
        System.out.println("Arrays match? " + arr1elems.equals(arr2elems));
    }
}

$ java -cp .:gson-2.2.2.jar CompareArray '[{"key1":"value1"},
{"key2":"value2"}, {"key3":"value3"}]' '[{"key3":"value3"},
{"key1":"value1"}, {"key2":"value2"}]'
Arrays match? true 

Надеюсь, это поможет вам.

person Siva Sonai    schedule 19.05.2015
comment
спасибо, Шива ... это выглядит полезным, надеюсь, он будет хорошо работать в моем проекте ... после этого примет ваш ответ, tx !! - person Green; 19.05.2015

Вы можете просто использовать класс для определения своего объекта и JSONObject , чтобы проанализировать ваш объект JSON и получить его свойства:

Класс Java:

public class MyObject{
     private String state; //either int or String
     private String cmd;
     //getters and setters
}

Ваш синтаксический анализ должен быть таким:

MyObject obj = new MyObject();
JSONParser jsonParser = new JSONParser();
 // input is your string here
JSONObject jsonObject = (JSONObject) jsonParser.parse(input);

//get properties here and set them in your object
obj.setState(jsonObject.get("state"));
obj.setCmd(jsonObject.get("cmd"));

А когда у вас есть два объекта, вы можете легко сравнить их свойства.

person cнŝdk    schedule 19.05.2015
comment
очень полезно, большое спасибо, воспользуюсь этим !! ... тоже очень просто .. приму после попытки - person Green; 19.05.2015
comment
Отлично, рад, что помог. - person cнŝdk; 19.05.2015
comment
.... tx alot for ur ответ ... это полезно, но я не использовал в своем коде ... для моего сценария использование карты лучше ..... но tx !! - person Green; 08.06.2015