16

I have a string like - {"state":1,"cmd":1} , I need to compare this with generated output but in the generated output the order keeps changing i.e. sometimes its {"state":1,"cmd":1} other times its {"cmd":1,"state":1}.

Currently I was using equals() method to compare, What can be better way in this scenario to validate the two strings. My concern is just that both entries are present in string, order is not imp.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Green
  • 653
  • 3
  • 6
  • 13
  • 8
    Parse the strings, construct two instances of a custom class and compare them. – Konstantin Yovkov May 19 '15 at 12:02
  • 1
    `equals` is not the same as *comparing*. *Comparing* means there is an order-relation, whereas *equality checks* one checks if two objects are the same. – Willem Van Onsem May 19 '15 at 12:04
  • You will need to write something more sophisticated like @kocko suggested. Parse the string for what you are interested in and compare then. – Juru May 19 '15 at 12:04
  • Both Strings should be treated as equal even if the order is different? It that what you are saying? – Soumitri Pattnaik May 19 '15 at 12:05
  • @SoumitriPattnaik ....ya – Green May 19 '15 at 12:13
  • @JarrodRoberson: I think this is not a full duplicate since the question asks about comparing two JSON *strings*. A potentially different answer is a program that does comparison at string level, without the need to fully decode (and *store*) both objects in memory. – Willem Van Onsem May 19 '15 at 13:23
  • please explain how you can compare JSON encoded as a string without parsing it? the strings are not the same unless they are parsed, plain and simple, the correct answer is to parse it and compare as some kind of object regardless, just as all the answers here say to do, it is a duplicate in practice and spirit. –  May 19 '15 at 13:31
  • @JarrodRoberson: for huge strings you read from file, you might for instance be interested in constructing a *push-down* automaton, that enumerates over the keys/values of the file and then looks whether these can be found in the second file. If your file is 20GiB+ but with every element being less than 100MiB of size, parsing it does not fit in memory, whereas doing text processing can check whether the objects are equal. Compare this with file duplicate scans: you don't keep in memory all files of the disk (you don't parse them), you calculate hashes and then compare two filestreams. – Willem Van Onsem May 19 '15 at 13:34
  • if you have a 20GB JSON encoded string you have bigger issues to deal with, your example is not the same as the example posed in the question, completely different problem domain –  May 19 '15 at 13:44
  • Like what? It can be a dump of some database. If the SO dump is 60+ GiB in XML why can one not use JSON instead. There are XPath query systems built (like a SAX parser) to run on XML files that require only a few megabytes of memory to process 100GiB+ files. – Willem Van Onsem May 19 '15 at 13:46

4 Answers4

16

Jackson Json parser has a nice feature that it can parse a Json String into a Map. You can then query the entries or simply ask on equality:

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

The output is

{state=1, cmd=1}
{cmd=1, state=1}
true
Sharon Ben Asher
  • 13,849
  • 5
  • 33
  • 47
15

You can also use 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));
Rockstar
  • 2,228
  • 3
  • 20
  • 39
1

Try this

 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 

I trust this is helpful to you.

Siva Sonai
  • 107
  • 12
  • thank you Siva ...this looks useful hopefully it will run in my project well ..will accept your ans after that , tx!! – Green May 19 '15 at 12:21
0

You can simply use a class to define your object and JSONObject to parse your JSON object and get its properties:

Java Class:

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

Your parsing should be like this:

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

And then when you have the two objects you can easily compare their properties.

cнŝdk
  • 31,391
  • 7
  • 56
  • 78
  • very useful, thanks alot, will use this!!...very simple too..will accept after trying – Green May 19 '15 at 12:23
  • ....tx alot for ur reply ..its useful but i didn't used in my code ...for my scenario using a map is better .....but tx!! – Green Jun 08 '15 at 07:30