前言
这里的JSON对象指的就是JsonNode对象,他有点类似HTML中的DOM节点;
有时候我们解析Json字符串,不知道具体的解析对象,可以将其解析为JsonNode对象,然后通过asText()等方法取出对应的值;
今天我们要讨论的就是如何比较两个JsonNode对象;
目录
- JsonNode包含浮点数
正文
1. 比较0
和0.0
a. 默认的比较方式:
比如有下面的两个Json字符串:
String s1 = "{\"name\":\"jalon\", \"weight\": 100}";
String s2 = "{\"name\":\"jalon\", \"weight\": 100.0}";
可以看到,一个体重100,一个体重100.0,严格意义来讲,他俩是不相等的;
通过JsonNode.equals()方法进行比较,代码如下所示:
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(s1);
JsonNode jsonNode2 = objectMapper.readTree(s2);
System.out.println(jsonNode.equals(jsonNode2));
此时输出为:false;符合预期
可以看到,默认的equals比较,会把100和100.0当作不同的数值进行对待;
但是有时候我们不希望看到这样的结果,我们希望的是100==100.0,这时就需要用到自定义的比较器;
b. 自定义的比较器:
这时我们就可以自己定义一个简易的比较器,专门用来处理这种0!=0.0的情况;
大致的思路就是向上转型,将0转为高精度的0.0,然后进行比较;这样可以保留数据的精度;
比较器如下所示:
public class NumericNodeComparator implements Comparator<JsonNode>
{
@Override
public int compare(JsonNode o1, JsonNode o2)
{
if (o1.equals(o2)){
return 0;
}
if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)){
Double d1 = o1.asDouble();
Double d2 = o2.asDouble();
if (d1.compareTo(d2) == 0) {
return 0;
}
}
return 1;
}
}
这里面的NumericNode是JsonNode的一个字类,代表数值类型的Json对象;
下面我们用这个自定义的比较器进行比较,代码如下:
NumericNodeComparator comparator = new NumericNodeComparator();
System.out.println(jsonNode.equals(comparator, jsonNode2));
此时输出为true,符合新的预期;
2. 比较name
和NAME
a. 默认的比较方式:
Java中的String类型进行比较时,可以选择是否忽略大小写,如下所示:
但是JsonNode并没有提供这种方式,JsonNode对字符串的相等处理,默认的方式是关心大小写,既大小写不一致,则不相等;
比如有下面的两条数据:
String s3 = "{\"name\":\"jalon\"}";
String s4 = "{\"name\":\"Jalon\"}";
默认的equals会认为这俩name是不相等的:
boolean equals = objectMapper.readTree(s3).equals(objectMapper.readTree(s4));
System.out.println(equals);
输出false;
b. 自定义的比较器:
我们可以跟上面的0和0.0一样,自己定义一个字符串的比较器,然后内部进行对比时,用String.equalsIgnoreCase()来忽略大小写;
自定义的比较器如下所示:
public class TextNodeComparator implements Comparator<JsonNode>
{
@Override
public int compare(JsonNode o1, JsonNode o2) {
if (o1.equals(o2)) {
return 0;
}
if ((o1 instanceof TextNode) && (o2 instanceof TextNode)) {
String s1 = o1.asText();
String s2 = o2.asText();
if (s1.equalsIgnoreCase(s2)) {
return 0;
}
}
return 1;
}
}
测试代码如下:
TextNodeComparator comparator1 = new TextNodeComparator();
boolean equals2 = objectMapper.readTree(s3).equals(comparator1, objectMapper.readTree(s4));
System.out.println(equals2);
输出true,符合新的预期;
3. 比较嵌套的对象
很多时候,我们在操作Json数据都会遇到嵌套多个对象的情况,如下所示:里面嵌套了friend对象;
String s6 = "{\"name\":\"jalon\", \"friend\": {\"name\":\"xiao\"}}";
关于嵌套的对象,我们可以通过一个简单的例子来看下,会不会影响Json对象的比较;
这里我们再创建两个Json字符串,且都嵌套一个对象:
String s6 = "{\"name\":\"jalon\", \"friend\": {\"name\":\"xiao\"}}";
String s7 = "{\"name\":\"jalon\", \"friend\": {\"name\":\"da\"}}";
然后用JsonNode默认的比较器进行比较:
JsonNode jsonNode6 = objectMapper.readTree(s6);
JsonNode jsonNode7 = objectMapper.readTree(s7);
System.out.println(jsonNode6.equals(jsonNode7));
输出false,说明JsonNode对象支持嵌套对象的比较;
4. 比较嵌套的集合
如果有嵌套的集合在Json对象中,是否也可以进行比较操作呢?
按照上面嵌套对象的逻辑来看,应该是可以的,下面我们看下例子:
String s8 = "{\"name\":\"jalon\", \"girlFriend\": [{\"name\":\"xiaomei\"}]}";
String s9 = "{\"name\":\"jalon\", \"girlFriend\": [{\"name\":\"lili\"}]}";
JsonNode jsonNode8 = objectMapper.readTree(s8);
JsonNode jsonNode9 = objectMapper.readTree(s9);
System.out.println(jsonNode8.equals(jsonNode9));
输出false,说明嵌套的集合也是可以进行比较的;
总结
Json对象的比较器,默认行为有:
-
比较0和0.0时,false,会关注数据精度;
-
比较name和Name,false,会关注大小写;
-
会比较嵌套的对象;
-
会比较嵌套的集合;
如果想要修改比较器的默认行为,可以自己实现一个比较器,然后在执行equals方法时传进去;
评论区