[JavaScript] Json 字串判斷是否相同(忽略順序)

今天偷懶一點直接交程式碼 今天收到一個題目,比較兩個 json 內容是否相等,但是需要忽略屬性和陣列的順序。還有一個隱藏限制,就是大多數的套件都不能使用,因為要放在 Postman 的 Test 內(測試了一下居然可以使用 Lodash)。

寫了半天,簡單來說就是將 json 轉成物件,循環比對,直接上程式碼:
    
    /**
     * 深度比較兩個物件是否相等
     * @author Ruyut <a@ruyut.com>
     * @param obj1
     * @param obj2
     * @returns {boolean}
     */
    function deepEqual(obj1, obj2) {
        if (obj1 === obj2) return true;
        if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) return false;

        const keysA = Object.keys(obj1);
        const keysB = Object.keys(obj2);
        // 比對屬性數量是否相同,若不同則直接回傳 false,若相同則下面的 keysA 迴圈就不用把 keysB 也跑一次
        if (keysA.length !== keysB.length) return false;

        for (let key of keysA) {
            if (!keysB.includes(key)) return false;

            if (Array.isArray(obj1[key])) {
                if (!Array.isArray(obj2[key])) return false; // 一個是陣列一個不是陣列就直接回傳 false

                if (!deepEqual(obj1[key].sort(), obj2[key].sort())) return false;
            } else {
                if (!deepEqual(obj1[key], obj2[key])) return false; // 進行深度比較
            }
        }

        return true;
    }
    

範例題目1:
    
const json1 = '[{"A":"a","B":"b"}]';
const json2 = '[{"B":"b","A":"a"}]';
const obj1 = JSON.parse(json1);
const obj2 = JSON.parse(json2);
console.log(`比對結果: ${deepEqual(obj1, obj2)}`); // 比對結果: true
    

範例題目2:
    
const json1 = '{"C":["c1", "c2"], "A": "a", "AA": {                "B3": "b3", "A3": "a3"}, "B": "b"}';
const json2 = '{"B": "b", "A": "a", "AA": {"A3": "a3", "B3": "b3"}, "C": ["c2", "c1"]}';
const obj1 = JSON.parse(json1);
const obj2 = JSON.parse(json2);

console.log(`比對結果: ${deepEqual(obj1, obj2)}`); // 比對結果: true
    

你有更好的做法嗎?歡迎留言!

留言