如何深入比较两个JSON,无论是数组内部还是没有JSON.stringify的对象?

时间:2019-04-12 18:17:13

标签: javascript json mongodb object

我试图跟踪通过GET发送的mongoDB记录在PUT req中是否已更改

当提出要求时,在更新之前和更新新记录之后,我都会使用doc,我会将现有记录与更新后的记录进行比较。 我跳过了诸如updated_at之类的项目,并跳过了一些比较字段

这是我的代码 当我调用此比较递归函数时出现了问题

对于同一数组,返回修改为true
有什么建议吗?

这是我的jsfiddle

https://jsfiddle.net/vrw2ghja/8/

_existingObj,_updatedObj是两个不同的对象,而_cloneOf_existingObj是_existingObj的副本

   
        
                
 const compare = (obj1, obj2) => {
 
       let isModified = false;
       let keyToRemove = ['id', 'updated_at', 'size', 'position'];
       let _oldObj = Object.keys(obj1);
       let _updatedObj = Object.keys(obj2)
       const oldObj = _oldObj.filter(item => keyToRemove.indexOf(item) < 0);
       const updatedObj = _updatedObj.filter(item => keyToRemove.indexOf(item) < 0);
              
       if (oldObj.length !== updatedObj.length) {
              isModified = true;
          } else {
                     oldObj.forEach(key => {                        
                        const oldObjValue = obj1[key],
                              newObjValue = obj2[key];
                         
                         if (Array.isArray(oldObjValue) === true) {
                             
                             if (Array.isArray(newObjValue) === false) {
                                 console.log(oldObjValue + "is Array and" + newObjValue + "is not Array");
                                 isModified = true;
                             } else {
                                 		 const allSubObjs = [].concat(
                                     Object.keys(oldObjValue).map(subKey => oldObjValue[subKey]),
                                     Object.keys(newObjValue).map(subKey => newObjValue[subKey])
                                 );
                                 allSubObjs.splice(1).forEach(subObj => {
                                     const recursiveCheck = compare(allSubObjs[0], subObj);
                                     if (recursiveCheck === false) {
                                         console.log("value changed for " + key + " old value " + oldObjValue + " new value " + newObjValue);
                                         isModified = true;
                                     }
                                 });
                             }
                         } else if (typeof oldObjValue !== typeof newObjValue) {
                             console.log("value changed for " + key + " old value " + oldObjValue + " new value " + newObjValue);
                             isModified = true;
                         }
                     });
                 }
                 return isModified;
             };
             
             
const check = (a, b) => {
       console.log("==========================");
       console.log(`Rug objects ${a} and ${b} are modified? ${compare(a, b)}`);
     
    }


 var _existingObj={
  "status": "available",
  "description": "sdfds s  sfs",
  "productType": "Tapestry",
  "otherTags": [
    
  ],
  "pattern": "Floral",
  "shapeCategoryTags": [
    "Square"
  ],
  "sizeCategoryTags": [
    "5x8"
  ],
  "_id": "5caf9758cba2cd5606c1bc8b",
  "tags": [
    {
      "name": "ABC",
      "_id": "59c57e33b9073f00048e8e8b"
    },
    {
      "name": "XYZ",
      "_id": "59c57e44b9073f00048e8e8e"
    },
    {
      "name": "PQR",
      "_id": "59c57e3fb9073f00048e8e8d"
    }
  ],
  "price": 150000,
  "created_at": "2019-04-11T19:36:56.673Z",
  "updated_at": "2019-04-12T17:33:50.288Z",
  "ID": 1005,
  "__v": 0,
  "images": [
    
  ],
  "id": "5caf9758cba2cd5606c1bc8b"
};



var _updatedObj={
  "_id": "5caf9758cba2cd5606c1bc8b",
  "status": "available",
  "description": "sdfds s  sfs",
  "productType": "Tapestry",
  "otherTags": [
    
  ],
  "pattern": "Floral",
  "shapeCategoryTags": [
    "Square"
  ],
  "sizeCategoryTags": [
    "5x8"
  ],
  "palette": "",
  "region": "East Turkestan",
  "primaryColor": "",
  "styleTags": [
    "traditional"
  ],
  "colourTags": [
    {
      "name": "ABC",
      "_id": "59c57e33b9073f00048e8e8b"
    },
    {
      "name": "XYZ",
      "_id": "59c57e44b9073f00048e8e8e"
    },
    {
      "name": "QWE",
      "_id": "59c57e3fb9073f00048e8e8d"
    }
  ],
  "price": 150000,
  "created_at": "2019-04-11T19:36:56.673Z",
  "updated_at": "2019-04-12T17:49:59.568Z",
  "ID": 1005,
  "__v": 0,
  "imageList": [
    
  ]
};



var _cloneOf_existingObj={
  "status": "available",
  "description": "sdfds s  sfs",
  "productType": "Tapestry",
  "otherTags": [
    
  ],
  "pattern": "Floral",
  "shapeCategoryTags": [
    "Square"
  ],
  "sizeCategoryTags": [
    "5x8"
  ],
  "_id": "5caf9758cba2cd5606c1bc8b",
  "tags": [
    {
      "name": "ABC",
      "_id": "59c57e33b9073f00048e8e8b"
    },
    {
      "name": "XYZ",
      "_id": "59c57e44b9073f00048e8e8e"
    },
    {
      "name": "PQR",
      "_id": "59c57e3fb9073f00048e8e8d"
    }
  ],
  "price": 150000,
  "created_at": "2019-04-11T19:36:56.673Z",
  "updated_at": "2019-04-12T17:33:50.288Z",
  "ID": 1005,
  "__v": 0,
  "images": [
    
  ],
  "id": "5caf9758cba2cd5606c1bc8b"
};

           
                
    
check(_existingObj, _updatedObj);   
check(_existingObj,_cloneOf_existingObj);

`

1 个答案:

答案 0 :(得分:0)

您可以编写一个将其分解为几个步骤的函数。

  1. 如果参数不是对象,则只需返回===的结果
  2. 如果它们是对象,但是键不同或键数不同,则返回false
  3. 如果您已经做到了这一点,则将这些值递归地传递回该函数中,并确保它们全部通过上述测试

  function deepEqual(obj1, obj2){
      // step 1
      if ( obj1 === null || obj2 === null || typeof obj1 !=='object' || typeof obj2 !=='object') return obj1 === obj2
      let [k1, k2] = [ Object.keys(obj1), Object.keys(obj2) ]
      // step 2
      if (k1.length !== k2.length || !k1.every(k => k2.includes(k))) return false
      //step 3
      return k1.every(k => deepEqual(obj1[k], obj2[k]))
  }

// test some examples:

console.log("true ->", deepEqual([1, {name:"Mark", data:{age:30}}], [1, {name:"Mark",  data:{age:30}}]))
// extra parameter
console.log("false ->", deepEqual([1, {name:"Mark", data:{age:30}}], [1, {name:"Mark",  data:{age:30, city:"Paris"}}]))

// different age
console.log("false ->", deepEqual([1, {name:"Mark", data:{age:30}}], [1, {name:"Mark",  data:{age:31}}]))

// literal 
console.log("true ->", deepEqual(30, 30))
console.log("true ->", deepEqual(null, null))

// array 
console.log("true ->", deepEqual([30, [31, 32]], [30,  [31, 32]])) //equal
console.log("false ->", deepEqual([30, [31, 32]], [30,  [32, 31]])) //not equal