Как сравнить два JSON в глубине, будь то массив внутри или объект без JSON.stringify? - PullRequest
0 голосов
/ 12 апреля 2019

Я пытаюсь отследить, изменилась ли запись mongoDB, которую я отправил через GET, или нет в PUT req

при появлении запроса req я получаю отличный документ перед обновлением, а после обновления новой записи я сравниваю существующую с обновленной записью. Я пропускаю какой-то элемент, например 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 голосов
/ 12 апреля 2019

Вы можете написать функцию, которая разбивает ее на шаги.

  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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...