使用JSONObject比较Java复杂对象

前提

       在Java编程中,我们经常要对引用数据类型的对象进行比较。引用数据类型的比较可以通过重写model的equals()方法实现,但是如果在开发中期才来重写equals()方法有可能对已有代码的正常运行有所影响。这种情况大家可以尝试本文推荐的方法对引用数据类型对象进行比较。步骤概述:

  1. 把Java对象转成JSONObject对象
  2. 使用JSONCompare对两者进行比较
  3. 如果需要忽略一些field可以使用Gson

准备

       先准备两个Model:Company和Employee,其中在Company下有一个Employee的数组。

Company.java

package com.demo.model;

import java.util.ArrayList;
import java.util.List;

public class Company {
    private String companyName;
    private List<Employee> employees;

    public String getCompanyName() { return companyName; }

    public void setCompanyName(String companyName) { this.companyName = companyName; }

    public List<Employee> getEmployees() {
        if (this.employees == null) this.employees = new ArrayList<>();
        return employees; }

    public void addEmployee(Employee employee) { this.getEmployees().add(employee); }
}

Employee.java

package com.demo.model;

public class Employee {
    private String employeeName;
    private int level;

    public String getEmployeeName() { return employeeName; }

    public void setEmployeeName(String employeeName) { this.employeeName = employeeName; }

    public int getLevel() { return level; }

    public void setLevel(int level) { this.level = level; }
}

       可以看到,Company里除了有基本数据类型的成员变量外,也包含了引用数据类型Employee的数组,接下来我们会把Java对象转成JSONObject来进行比较。因为我们要用到JSONObject,所以还需要引入如下jar包。

开始

  • 直接调用equals()方法

        当我们直接调用Company对象的equals()方法时,因为比较的是两者的toString()方法的结果,所以除非我们重写了equals()方法的实现,否则哪怕里面的值完全一样,equals()得到的结果也是false的。

package com.demo;

import com.demo.model.Company;
import com.demo.model.Employee;

public class GsonDemoApplication {
    public static void main(String[] args) {
        Company company1 = new Company();
        company1.setCompanyName("ABC");

        Company company2 = new Company();
        company2.setCompanyName("ABC");

        Employee employee1 = getEmployee1();
        Employee employee2 = getEmployee1();

        company1.addEmployee(employee1);
        company2.addEmployee(employee2);

        if (company1.equals(company2))
            System.out.println("Same");
        else
            System.out.println("Different");
    }

    private static Employee getEmployee1() {
        Employee employee = new Employee();
        employee.setEmployeeName("Jay");
        employee.setLevel(2);
        return employee;
    }
}

结果:

Different
  • 转成JSONObject对象之后使用JSONCompare进行比较

        因为我们要用到JSONObject和JSONCompare,所以需要引入如下jar包。

<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20160810</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.skyscreamer/jsonassert -->
<dependency>
    <groupId>org.skyscreamer</groupId>
    <artifactId>jsonassert</artifactId>
    <version>1.5.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.skyscreamer</groupId>
    <artifactId>jsonassert</artifactId>
    <version>RELEASE</version>
    <scope>compile</scope>
</dependency>

        使用skyscreamer提供的JSONCompare对两个JSONObject对象进行比较,得到JSONCompareResult,可以打印两者的差异。

package com.demo;

import com.demo.model.Company;
import com.demo.model.Employee;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.JSONCompare;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.JSONCompareResult;

public class GsonDemoApplication {
    public static void main(String[] args) {
        Company company1 = new Company();
        company1.setCompanyName("ABC");

        Company company2 = new Company();
        company2.setCompanyName("ABC");

        Employee employee1 = getEmployee1();
        Employee employee2 = getEmployee2();

        company1.addEmployee(employee1);
        company2.addEmployee(employee2);

        JSONObject object1 = new JSONObject(company1);
        JSONObject object2 = new JSONObject(company2);

        JSONCompareResult compareResult = JSONCompare.compareJSON(object1, object2, JSONCompareMode.STRICT);
        if (compareResult.passed())
            System.out.println("Same");
        else {
            System.out.println("Different");
            System.out.println("Failures:" + compareResult.getFieldFailures());
            System.out.println("Unexpected:" + compareResult.getFieldUnexpected());
            System.out.println("Missing:" + compareResult.getFieldMissing());
            System.out.println("Message:" + compareResult.getMessage());
        }
    }

    private static Employee getEmployee1() {
        Employee employee = new Employee();
        employee.setEmployeeName("Jay");
        employee.setLevel(2);
        return employee;
    }

    private static Employee getEmployee2() {
        Employee employee = new Employee();
        employee.setEmployeeName("Susan");
        employee.setLevel(3);
        return employee;
    }
}

结果:

Different
Failures:[org.skyscreamer.jsonassert.FieldComparisonFailure@7a81197d, org.skyscreamer.jsonassert.FieldComparisonFailure@5ca881b5]
Unexpected:[]
Missing:[]
Message:employees[0].employeeName
Expected: Jay
     got: Susan
 ; employees[0].level
Expected: 2
     got: 3
  • 使用JSONCompare避免因数组元素顺序的影响

        JSONCompare比较的时候是根据key来取值比较的,所以field的顺序可以不用管,但是数组里元素的顺序呢?只要我们使用JSONCompareMode.LENIENT模式就能够忽略数组元素顺序的影响,如果不想忽视这个影响,可以像上例一样使用JSONCompareMode.STRICT模式。

package com.demo;

import com.demo.model.Company;
import com.demo.model.Employee;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.JSONCompare;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.JSONCompareResult;

public class GsonDemoApplication {
    public static void main(String[] args) {
        Company company1 = new Company();
        company1.setCompanyName("ABC");

        Company company2 = new Company();
        company2.setCompanyName("ABC");

        Employee employee1 = getEmployee1();
        Employee employee2 = getEmployee2();

        company1.addEmployee(employee1);
        company1.addEmployee(employee2);

        company2.addEmployee(employee2);
        company2.addEmployee(employee1);

        JSONObject object1 = new JSONObject(company1);
        JSONObject object2 = new JSONObject(company2);

        JSONCompareResult compareResult = JSONCompare.compareJSON(object1, object2, JSONCompareMode.LENIENT);
        if (compareResult.passed())
            System.out.println("Same");
        else {
            System.out.println("Different");
            System.out.println("Failures:" + compareResult.getFieldFailures());
            System.out.println("Unexpected:" + compareResult.getFieldUnexpected());
            System.out.println("Missing:" + compareResult.getFieldMissing());
            System.out.println("Message:" + compareResult.getMessage());
        }
    }

    private static Employee getEmployee1() {
        Employee employee = new Employee();
        employee.setEmployeeName("Jay");
        employee.setLevel(2);
        return employee;
    }

    private static Employee getEmployee2() {
        Employee employee = new Employee();
        employee.setEmployeeName("Susan");
        employee.setLevel(3);
        return employee;
    }
}

结果:

Same
  • 如何忽视部分field的影响

        在某些业务场景,我们需要比较两个对象的同时又要忽略其中的一些field,这个时候我们就可以使用Gson。

<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.2</version>
</dependency>

        下例中,虽然companyName是不一样的,但是我们在转json的时候跳过了这个field,所以也就不影响我们比较的结果。

package com.demo;

import com.demo.model.Company;
import com.demo.model.Employee;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.JSONCompare;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.JSONCompareResult;

public class GsonDemoApplication {
    public static void main(String[] args) {
        Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                return fieldAttributes.getName().equals("companyName");
            }

            @Override
            public boolean shouldSkipClass(Class<?> aClass) {
                return false;
            }
        }).create();

        Company company1 = new Company();
        company1.setCompanyName("ABC");

        Company company2 = new Company();
        company2.setCompanyName("ABCD");

        Employee employee1 = getEmployee1();
        Employee employee2 = getEmployee2();

        company1.addEmployee(employee1);
        company1.addEmployee(employee2);

        company2.addEmployee(employee2);
        company2.addEmployee(employee1);

        JSONObject object1 = new JSONObject(gson.toJson(company1));
        JSONObject object2 = new JSONObject(gson.toJson(company2));

        JSONCompareResult compareResult = JSONCompare.compareJSON(object1, object2, JSONCompareMode.LENIENT);
        if (compareResult.passed())
            System.out.println("Same");
        else {
            System.out.println("Different");
            System.out.println("Failures:" + compareResult.getFieldFailures());
            System.out.println("Unexpected:" + compareResult.getFieldUnexpected());
            System.out.println("Missing:" + compareResult.getFieldMissing());
            System.out.println("Message:" + compareResult.getMessage());
        }
    }

    private static Employee getEmployee1() {
        Employee employee = new Employee();
        employee.setEmployeeName("Jay");
        employee.setLevel(2);
        return employee;
    }

    private static Employee getEmployee2() {
        Employee employee = new Employee();
        employee.setEmployeeName("Susan");
        employee.setLevel(3);
        return employee;
    }
}

结果:

Same

        这就是本篇文章的全部内容,需要另外提出的一点事,Gson还有很多强大的功能,大家可以自己探索哦~

猜你喜欢

转载自blog.csdn.net/Jay_Wooz/article/details/88547756
今日推荐