Testing two JSON objects for equality ignoring child order in Java
Try Skyscreamer's JSONAssert.
Its non-strict mode has two major advantages that make it less brittle:
- Object extensibility (e.g. With an expected value of {id:1}, this would still pass: {id:1,moredata:'x'}.)
- Loose array ordering (e.g. ['dog','cat']==['cat','dog'])
In strict mode it behaves more like json-lib's test class.
A test looks something like this:
@Testpublic void testGetFriends() { JSONObject data = getRESTData("/friends/367.json"); String expected = "{friends:[{id:123,name:\"Corby Page\"}" + ",{id:456,name:\"Solomon Duskis\"}]}"; JSONAssert.assertEquals(expected, data, false);}
The parameters in the JSONAssert.assertEquals() call are expectedJSONString, actualDataString, and isStrict.
The result messages are pretty clear, which is important when comparing really big JSON objects.
As a general architectural point, I usually advise against letting dependencies on a particular serialization format bleed out beyond your storage/networking layer; thus, I'd first recommend that you consider testing equality between your own application objects rather than their JSON manifestations.
Having said that, I'm currently a big fan of Jackson which my quick read of their ObjectNode.equals() implementation suggests does the set membership comparison that you want:
public boolean equals(Object o){ if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) { return false; } ObjectNode other = (ObjectNode) o; if (other.size() != size()) { return false; } if (_children != null) { for (Map.Entry<String, JsonNode> en : _children.entrySet()) { String key = en.getKey(); JsonNode value = en.getValue(); JsonNode otherValue = other.get(key); if (otherValue == null || !otherValue.equals(value)) { return false; } } } return true;}
Using GSON
JsonParser parser = new JsonParser();JsonElement o1 = parser.parse("{a : {a : 2}, b : 2}");JsonElement o2 = parser.parse("{b : 2, a : {a : 2}}");assertEquals(o1, o2);
Edit: Since GSON v2.8.6 the instance method JsonParser.parse
is deprecated. You have to use the static method JsonParser.parseString
:
JsonElement o1 = JsonParser.parseString("{a : {a : 2}, b : 2}");JsonElement o2 = JsonParser.parseString("{b : 2, a : {a : 2}}");assertEquals(o1, o2);