1. Overview
1.概述
JSON is a string representation of data. We may wish to compare this data in our algorithms or tests. And though it’s possible to compare strings containing JSON, string comparison is sensitive to differences in representation, rather than content.
JSON是一种数据的字符串表示。我们可能希望在我们的算法或测试中比较这些数据。尽管有可能比较包含JSON的字符串,但字符串比较对表示法的差异很敏感,而不是内容。
To overcome this and compare JSON data semantically, we need to load the data into a structure in memory that’s not affected by things like whitespace or by the order of an object’s keys.
为了克服这个问题并对JSON数据进行语义上的比较,我们需要将数据加载到内存中的一个结构中,该结构不受诸如空格或对象的键的顺序的影响。
In this short tutorial, we’ll solve this using Gson, a JSON serialization\deserialization library that can do a deep comparison between JSON objects.
在这个简短的教程中,我们将使用Gson来解决这个问题,这是一个JSON序列化/去序列化库,可以在JSON对象之间进行深度比较。
2. Semantically Identical JSON in Different Strings
2.不同字符串中语义相同的JSON
Let’s take a closer look at the problem we’re trying to solve.
让我们仔细看看我们要解决的问题。
Assume we have two strings, representing the same JSON data, but one of them has some extra spaces at the end of it:
假设我们有两个字符串,代表相同的JSON数据,但其中一个字符串的末尾有一些额外的空格。
String string1 = "{\"fullName\": \"Emily Jenkins\", \"age\": 27 }";
String string2 = "{\"fullName\": \"Emily Jenkins\", \"age\": 27}";
Although the content of the JSON objects is equal, comparing the above as strings will show a difference:
虽然JSON对象的内容是相同的,但将上述内容作为字符串进行比较会显示出差异。
assertNotEquals(string1, string2);
The same would happen if the order of keys in an object was varied, even though JSON is not usually sensitive to this:
如果一个对象中的键的顺序被改变,也会发生同样的情况,尽管JSON通常对此不敏感。
String string1 = "{\"fullName\": \"Emily Jenkins\", \"age\": 27}";
String string2 = "{\"age\": 27, \"fullName\": \"Emily Jenkins\"}";
assertNotEquals(string1, string2);
This is why it’s we’d benefit from using a JSON processing library to compare JSON data.
这就是为什么我们会从使用JSON处理库来比较JSON数据中受益。
3. Maven Dependency
3.Maven的依赖性
To use Gson, let’s first add the Gson Maven dependency:
要使用Gson,首先让我们添加Gson Maven依赖项。
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
4. Parsing JSON into Gson Objects
4.将JSON解析为Gson对象
Before we dive into comparing objects, let’s have a look at how Gson represents JSON data in Java.
在我们深入研究比较对象之前,让我们看看Gson如何在Java中表示JSON数据。
When working with JSON in Java, we first need to convert the JSON String into a Java object. Gson provides JsonParser which parses source JSON into a JsonElement tree:
在Java中处理JSON时,我们首先需要将JSON字符串转换成一个Java对象。Gson提供了JsonParser,它将源JSON解析成JsonElementtree。
JsonParser parser = new JsonParser();
String objectString = "{\"customer\": {\"fullName\": \"Emily Jenkins\", \"age\": 27 }}";
String arrayString = "[10, 20, 30]";
JsonElement json1 = parser.parse(objectString);
JsonElement json2 = parser.parse(arrayString);
JsonElement is an abstract class, representing an element of JSON. The parse method returns an implementation of JsonElement; either a JsonObject, JsonArray, JsonPrimitive or JsonNull:
JsonElement是一个抽象的类,代表JSON的一个元素。parse方法返回JsonElement的实现;要么是一个JsonObject、JsonArray、JsonPrimitive,要么是JsonNull:。
assertTrue(json1.isJsonObject());
assertTrue(json2.isJsonArray());
Each of those subclasses (JsonObject, JsonArray, etc.) overrides the Object.equals method, providing an effective deep JSON comparison.
每个子类(JsonObject, JsonArray, 等)覆盖Object.equals 方法,提供有效的深度JSON比较。
5. Gson Comparison Use Cases
5.Gson比较用例
5.1. Compare Two Simple JSON Objects
5.1.比较两个简单的JSON对象
Suppose we have two strings, representing simple JSON objects, where the order of keys is different:
假设我们有两个字符串,代表简单的JSON对象,其中键的顺序是不同的。
The first object has fullName earlier than age:
第一个对象的fullName早于age。
{
"customer": {
"id": 44521,
"fullName": "Emily Jenkins",
"age": 27
}
}
The second reverses the order:
其次是颠倒顺序。
{
"customer": {
"id": 44521,
"age": 27,
"fullName": "Emily Jenkins"
}
}
We can simply parse and compare them:
我们可以简单地对它们进行解析和比较。
assertEquals(parser.parse(string1), parser.parse(string2));
In this case, the JsonParser returns a JsonObject, whose equals implementation is not order-sensitive.
在这种情况下,JsonParser会返回一个JsonObject,其equals实现不是顺序敏感的。
5.2. Compare Two JSON Arrays
5.2.比较两个JSON数组
In a case of JSON arrays, JsonParser will return a JsonArray.
在JSON数组的情况下,JsonParser将返回一个JsonArray.。
If we have one array in one order:
如果我们有一个数组在一个订单中。
[10, 20, 30]
assertTrue(parser.parse(string1).isJsonArray());
We can compare it to another in a different order:
我们可以把它与另一个不同的顺序进行比较。
[20, 10, 30]
Unlike JsonObject, JsonArray‘s equals method is order-sensitive, so these arrays are not equal, which is semantically correct:
与JsonObject不同,JsonArray的equals方法是顺序敏感的,所以这些数组不相等,这在语义上是正确的。
assertNotEquals(parser.parse(string1), parser.parse(string2));
5.3. Compare Two Nested JSON Objects
5.3.比较两个嵌套的JSON对象
As we saw earlier, JsonParser can parse the tree-like structure of JSON. Each JsonObject and JsonArray contain other JsonElement objects, which can, themselves be of type JsonObject or JsonArray.
正如我们之前看到的,JsonParser可以解析JSON的树状结构。每个JsonObject和JsonArray都包含其他JsonElement对象,它们本身可以是JsonObject或JsonArray类型。
When we use equals, it compares all the members recursively, which means nested objects are also comparable:
当我们使用equals时,它会递归地比较所有成员,这意味着嵌套对象也是可以比较的:。
If this is string1:
如果这是string1。
{
"customer": {
"id": "44521",
"fullName": "Emily Jenkins",
"age": 27,
"consumption_info": {
"fav_product": "Coke",
"last_buy": "2012-04-23"
}
}
}
And this JSON is string2:
而这个JSON是string2。
{
"customer": {
"fullName": "Emily Jenkins",
"id": "44521",
"age": 27,
"consumption_info": {
"last_buy": "2012-04-23",
"fav_product": "Coke"
}
}
}
Then we can still use the equals method to compare them:
那么我们仍然可以使用equals方法来比较它们。
assertEquals(parser.parse(string1), parser.parse(string2));
6. Conclusion
6.结语
In this short article, we’ve looked at the challenges of comparing JSON as a String. We’ve seen how Gson allows us to parse those strings into an object structure that supports comparison.
在这篇短文中,我们已经了解了将JSON作为String进行比较的挑战。我们看到Gson是如何让我们将这些字符串解析为支持比较的对象结构的。
As always, the source code of the examples above can be found over on GitHub.
一如既往,上述例子的源代码可以在GitHub上找到。