Jackson Comparator

简介: 在日常开发中,我们经常去比较两个对象是否相等,如果此对象是josn反序列化的,那么还要对对象属性进行逐一比对,手写个工具类耗时耗力,那如何解决此类问题呢。

前言

image.png
在日常开发中,我们经常去比较两个对象是否相等,如果此对象是josn反序列化的,那么还要对对象属性进行逐一比对,手写个工具类耗时耗力,那如何解决此类问题呢。

JsonNode.equals

节点对象的相等定义为完全(深度)值相等。这意味着可以通过比较根节点的相等性来比较完整的JSON树的相等性。
我们可以使用ObjectMapper类将Json字符串转成JsonNode,然后使用JsonNode的equals方法。

ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(jsonStr);

JsonNode.equals方法支持执行完整(深度)比较。

Example-1

/**
 * 比较两个简单的 JSON 对象
 */
    public static void main(String[] args) throws IOException {
        String user1 = "{\n" +
                "  \"user\": {\n" +
                "    \"id\": \"10001\",\n" +
                "    \"name\": \"小明\",\n" +
                "    \"age\": 22\n" +
                "  }\n" +
                "}";
        String user2 = "{\n" +
                "  \"user\": {\n" +
                "    \"id\": \"10001\",\n" +
                "    \"age\": 22,\n" +
                "    \"name\": \"小明\"\n" +
                "  }\n" +
                "}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode1 = mapper.readTree(user1);
        JsonNode jsonNode2 = mapper.readTree(user2);
        System.out.println(jsonNode1.equals(jsonNode2));
    }

我们可以发现上文中的name与age的在Json中的属性顺序不相同,jsonNode1.equals也会忽略顺序并将它们视为相等。

Example-2

/**
 * 比较带有嵌套元素的两个 JSON 对象
 */
   public static void main(String[] args) throws IOException {
        String user1 = "{\n" +
                "  \"user\": {\n" +
                "    \"id\": \"10001\",\n" +
                "    \"name\": \"小明\",\n" +
                "    \"age\": 22,\n" +
                "    \"contact\": {\n" +
                "      \"email\": \"Duansg@163.com\",\n" +
                "      \"phone\": \"13912341234\"\n" +
                "    }\n" +
                "  }\n" +
                "}";
        String user2 = "{\n" +
                "  \"user\": {\n" +
                "    \"id\": \"10001\",\n" +
                "    \"age\": 22,\n" +
                "    \"name\": \"小明\",\n" +
                "    \"contact\": {\n" +
                "      \"email\": \"Duansg@163.com\",\n" +
                "      \"phone\": \"13912341234\"\n" +
                "    }\n" +
                "  }\n" +
                "}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode1 = mapper.readTree(user1);
        JsonNode jsonNode2 = mapper.readTree(user2);
        System.out.println(jsonNode1.equals(jsonNode2));
    }

同样,我们也不难发现,jsonNode1.equals方法也可以比较两个具有嵌套元素的Json。

Example-3

/**
 * 比较两个包含列表元素的 JSON 对象
 */
    public static void main(String[] args) throws IOException {
        String user1 = "{\n" +
                "  \"user\": {\n" +
                "    \"id\": \"10001\",\n" +
                "    \"name\": \"小明\",\n" +
                "    \"age\": 22,\n" +
                "    \"hobby\": [\"Java\", \"Python\"]\n" +
                "  }\n" +
                "}";
        String user2 = "{\n" +
                "  \"user\": {\n" +
                "    \"id\": \"10001\",\n" +
                "    \"age\": 22,\n" +
                "    \"name\": \"小明\",\n" +
                "    \"hobby\": [\"Java\", \"Python\"]\n" +
                "  }\n" +
                "}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode1 = mapper.readTree(user1);
        JsonNode jsonNode2 = mapper.readTree(user2);
        System.out.println(jsonNode1.equals(jsonNode2));
    }

同样,我们也不难发现,jsonNode1.equals方法也可以比较两个具有数组元素的Json,但是需要注意的是,只有当两个数组中的元素顺序完全相同时,才会被比视为相等。

Custom Comparator

Jackson还提供了JsonNode.equals(Comparator,JsonNode)方法来配置自定义Comparator对象,用来满足一些自定义需求。

Example-1

/**
 * 下述方法执行出来的结果是不相等的
 */
public static void main(String[] args) throws IOException {
        String user1 = "{\n" +
                "  \"user\": {\n" +
                "    \"name\": \"小明\",\n" +
                "  \t\"age\": 22.0\n" +
                "  }\n" +
                "}";
        String user2 = "{\n" +
                "  \"user\": {\n" +
                "    \"name\": \"小明\",\n" +
                "  \t\"age\": 22\n" +
                "  }\n" +
                "}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode1 = mapper.readTree(user1);
        JsonNode jsonNode2 = mapper.readTree(user2);
        System.out.println(jsonNode1.equals(jsonNode2));
    }
创建一个Comparator
   public static void main(String[] args) throws IOException {
        String user1 = "{\n" +
                "  \"user\": {\n" +
                "    \"name\": \"小明\",\n" +
                "  \t\"age\": 22.0\n" +
                "  }\n" +
                "}";
        String user2 = "{\n" +
                "  \"user\": {\n" +
                "    \"name\": \"小明\",\n" +
                "  \t\"age\": 22\n" +
                "  }\n" +
                "}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode1 = mapper.readTree(user1);
        JsonNode jsonNode2 = mapper.readTree(user2);
        NumericNodeComparator cmp = new NumericNodeComparator();
        System.out.println(jsonNode1.equals(cmp, jsonNode2));
    }


    public static 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;
        }
    }

Example-2

/**
 * 下述方法执行出来的结果是不相等的
 */
    public static void main(String[] args) throws IOException {
        String user1 = "{\n" +
                "  \"user\":{\n" +
                " \t\t\"name\": \"JACK\",\n" +
                "  \t\"age\": 22\n" +
                "  }\n" +
                "}";
        String user2 = "{\n" +
                "  \"user\":{\n" +
                " \t\t\"name\": \"jack\",\n" +
                "  \t\"age\": 22\n" +
                "  }\n" +
                "}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode1 = mapper.readTree(user1);
        JsonNode jsonNode2 = mapper.readTree(user2);
        System.out.println(jsonNode1.equals(jsonNode2));
    }
创建一个Comparator
 public static void main(String[] args) throws IOException {
        String user1 = "{\n" +
                "  \"user\":{\n" +
                " \t\t\"name\": \"JACK\",\n" +
                "  \t\"age\": 22\n" +
                "  }\n" +
                "}";
        String user2 = "{\n" +
                "  \"user\":{\n" +
                " \t\t\"name\": \"jack\",\n" +
                "  \t\"age\": 22\n" +
                "  }\n" +
                "}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode1 = mapper.readTree(user1);
        JsonNode jsonNode2 = mapper.readTree(user2);
        TextNodeComparator cmp = new TextNodeComparator();
        System.out.println(jsonNode1.equals(cmp, jsonNode2));
    }
    public static 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;
        }
    }

小结

当输入的Json元素值不完全相同时,但是你仍希望将它们视为相等时,就可以通过实现自定义比较器来进行处理。

目录
相关文章
|
4月前
|
Java API 开发者
|
7月前
|
Java
Java中的比较器Comparable与Comparator
Java中的比较器Comparable与Comparator
|
7月前
|
存储 Java
Java中比较器Comparator的使用
Java中比较器Comparator的使用
58 0
|
JSON 前端开发 Java
Java——jackson的注解@JsonProperty、@JsonIgnore、@JsonIgnoreProperties、@JsonFormat、@JSONField
Java——jackson的注解@JsonProperty、@JsonIgnore、@JsonIgnoreProperties、@JsonFormat、@JSONField
|
Java
Java对象的比较和排序(Comparator和Comparable)
Java对象的比较和排序(Comparator和Comparable)
159 0
Java对象的比较和排序(Comparator和Comparable)
|
Java
Java - Map 使用 Comparator 排序
Java - Map 使用 Comparator 排序
612 0
|
Java 测试技术 Spring
【小家Java】聊聊Java中的比较器(排序):Comparable和Comparator;Spring中的Comparators和AnnotationAwareOrderComparator(下)
【小家Java】聊聊Java中的比较器(排序):Comparable和Comparator;Spring中的Comparators和AnnotationAwareOrderComparator(下)
|
算法 搜索推荐 Java
【小家Java】聊聊Java中的比较器(排序):Comparable和Comparator;Spring中的Comparators和AnnotationAwareOrderComparator(上)
【小家Java】聊聊Java中的比较器(排序):Comparable和Comparator;Spring中的Comparators和AnnotationAwareOrderComparator(上)
|
Apache
org.apache.commons.lang.StringUtils的常用方法
org.apache.commons.lang.StringUtils的常用方法
1067 0
|
Java
Java Comparable和Comparator(1)
Java Comparable和Comparator
121 0