使用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還有很多強大的功能,大家可以自己探索哦~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章