如何比较嵌套对象的更改并创建更改报告

问题描述 投票:0回答:1

我有两个来自应用程序的 JSON 文件。

我需要比较它们的变化并创建变化报告。

我基本上可以做到这一点,但我在创建对象内已更改的嵌套对象的报告时遇到困难。

我可以看到对象已更改,并且我可以回发整个对象。我的问题是,其中一些可能有数十甚至数百个键值对,并且很难找到对象的哪些条目被更改。

如何将两个 JSON 文件与所需的报告结构(如下所示)进行比较,以将对象与两个 JSON 文件的嵌套对象进行匹配?

如果每个文件中的两个对象

ids
匹配,则它们匹配。

在我的示例中,有一个匹配的对象对与嵌套

options
对象,扇区/扇区2,但可能存在多个匹配的配对。

(我对所有代码表示歉意)

为了方便起见,我创建了一个 Google 表格,其中显示了所有代码 https://docs.google.com/spreadsheets/d/1G2c1qsBvW5rW9Z0yRbF6OhBkw8cZ7U5XHY0Ab0u2z-M/edit?usp=sharing

谢谢

let oldJSON = [
 {
  "id": "c3c6f410f58e5836431b473ebcf134756232d04f2bf35edff8",
  "label": "Sector2",
  "options": {
   "62f92fab79ac81d933765bd0bbc4a1f5ea26cb3a088bcb4e6e": {
    "index": 0,
    "value": "Bob",
    "label": "Bob"
   },
   "2fe91aa3567c0d04c521dcd2fc7e40d7622bb8c3f594d503da": {
    "index": 1,
    "value": "Student",
    "label": "Student"
   },
   "c59ea1159f33b91a7f6edc6925be5e373fc543e4": {
    "index": 2,
    "value": "BBB",
    "label": "BBB"
   },
   "c59ea1159f33b91a7f6edc6925be5e373fc54AAA": {
    "index": 3,
    "value": "Orange Duck",
    "label": "Orange Duck"
   }
  }
 },
 {
  "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e951709485",
  "label": "Brown Cow"
 },
 {
  "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e95170ZZZ",
  "label": "Red Fish"
 },
];

 let newJSON = [
 {
  "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e951709485",
  "label": "Green Frog"
 },
 {
  "id": "c3c6f410f58e5836431b473ebcf134756232d04f2bf35edff8",
  "label": "Sector",
  "options": {
   "62f92fab79ac81d933765bd0bbc4a1f5ea26cb3a088bcb4e6e": {
    "index": 0,
    "value": "Bob",
    "label": "Bob"
   },
   "c59ea1159f33b91a7f6edc6925be5e373DDDDDDDDD": {
    "index": 1,
    "value": "GrassLand",
    "label": "TreeLand"
   },
   "2fe91aa3567c0d04c521dcd2fc7e40d7622bb8c3f594d503da": {
    "index": 2,
    "value": "Student",
    "label": "Student"
   },
   "c59ea1159f33b91a7f6edc6925be5e373fc543e4": {
    "index": 3,
    "value": "AAA",
    "label": "AAA"
   }
  }
 },
 {
  "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e951709AAA",
  "label": "Blue Bird"
 }
];

到目前为止我的代码

  // Create an object to store the results of the comparison.
  const results = {};
  
  // Loop through the first array.
  for (const item1 of array1) {
    // Check if the item exists in the second array.
    let item2 = array2.find(item => item.id === item1.id);
    
    // If the item does not exist in the second array, add it to the results object as a deleted item.
    if (!item2) {
      results.deleted = results.deleted || [];
      results.deleted.push(item1);

    } else {
      // If the item exists in the second array, compare the two objects.
      const differences = compareObjects(item1, item2);
      
      // If there are any differences, add the item to the results object as a changed item.
      if (Object.keys(differences).length > 0) {
        
        results.changed = results.changed || [];
       
        let
          label1 = item1.label,
          label2 = item2.label;

        results.changed.push({
          label1,
          label2,
          differences,
        });
      }
    }
  }

  // Loop through the second array.
  for (const item2 of array2) {
    // Check if the item exists in the first array.
    const item1 = array1.find(item => item.id === item2.id);

    // If the item does not exist in the first array, add it to the results object as an added item.
    if (!item1) {
      results.added = results.added || [];
      results.added.push(item2);
    }
  }

  // Return the results object.
  return results;
}

function compareObjects(object1, object2) {
  // Create an object to store the differences between the two objects.
  const differences = {};

  // Loop through the keys of the first object.
  for (const key of Object.keys(object1)) {
    // Get the value of the key in the second object.
    const value2 = object2[key];

    // If the value does not exist in the second object, add it to the differences object as a deleted value.
    if (value2 === undefined) {
      differences[key] = {
        value1: object1[key],
        value2: undefined,
      };
    } else {
      // If the value exists in the second object, compare the two values.
      if (object1[key] !== value2) {
        differences[key] = {
          value1: object1[key],
          value2,
        };
      }
    }
  }

  // Loop through the keys of the second object.
  for (const key of Object.keys(object2)) {
    // Check if the key exists in the first object.
    if (!object1.hasOwnProperty(key)) {
      // If the key does not exist in the first object, add it to the differences object as an added value.
      differences[key] = {
        value1: undefined,
        value2: object2[key],
      };
    }
  }

  // Return the differences object.
  return differences;
}

我得到的输出

{
 "changed": [
  {
   "label1": "Sector2",
   "label2": "Sector",
   "differences": {
    "label": {
     "value1": "Sector2",
     "value2": "Sector"
    },
    "options": {
     "value1": {
      "62f92fab79ac81d933765bd0bbc4a1f5ea26cb3a088bcb4e6e": {
       "index": 0,
       "value": "Bob",
       "label": "Bob"
      },
      "2fe91aa3567c0d04c521dcd2fc7e40d7622bb8c3f594d503da": {
       "index": 1,
       "value": "Student",
       "label": "Student"
      },
      "c59ea1159f33b91a7f6edc6925be5e373fc543e4": {
       "index": 2,
       "value": "BBB",
       "label": "BBB"
      },
      "c59ea1159f33b91a7f6edc6925be5e373fc54AAA": {
       "index": 3,
       "value": "Orange Duck",
       "label": "Orange Duck"
      }
     },
     "value2": {
      "62f92fab79ac81d933765bd0bbc4a1f5ea26cb3a088bcb4e6e": {
       "index": 0,
       "value": "Bob",
       "label": "Bob"
      },
      "c59ea1159f33b91a7f6edc6925be5e373DDDDDDDDD": {
       "index": 1,
       "value": "GrassLand",
       "label": "TreeLand"
      },
      "2fe91aa3567c0d04c521dcd2fc7e40d7622bb8c3f594d503da": {
       "index": 2,
       "value": "Student",
       "label": "Student"
      },
      "c59ea1159f33b91a7f6edc6925be5e373fc543e4": {
       "index": 3,
       "value": "AAA",
       "label": "AAA"
      }
     }
    }
   }
  },
  {
   "label1": "Brown Cow",
   "label2": "Green Frog",
   "differences": {
    "label": {
     "value1": "Brown Cow",
     "value2": "Green Frog"
    }
   }
  }
 ],
 "deleted": [
  {
   "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e95170ZZZ",
   "label": "Red Fish"
  }
 ],
 "added": [
  {
   "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e951709AAA",
   "label": "Blue Bird"
  }
 ]
}

所需的输出或等效的东西

{
 "changed": [
  {
   "label1": "Sector2",
   "label2": "Sector",
   "differences": {
    "label": {
     "value1": "Sector2",
     "value2": "Sector"
    },
    "options": {
     "value1": {
      "c59ea1159f33b91a7f6edc6925be5e373fc54AAA": {
       "deleted": {
       "index": 3,
       "value": "Orange Duck",
       "label": "Orange Duck"
      }
      }
     },
     "value2": {
      "added":{
      "c59ea1159f33b91a7f6edc6925be5e373DDDDDDDDD": {
       "index2": 1,
       "value": "GrassLand",
       "label": "TreeLand"
       }
      },
      "2fe91aa3567c0d04c521dcd2fc7e40d7622bb8c3f594d503da": {
       "changed": {
       "index1": 1,
       "index2": 2,
       "value1": "Student",
       "value2": "Student",
       "label1": "Student",
       "label2": "Student"
       }
      },
      "c59ea1159f33b91a7f6edc6925be5e373fc543e4": {
       "changed": {
       "index1": 2,
       "index2": 3,
       "value1": "BBB",
       "value2": "AAA",
       "label1": "BBB",
       "label2": "AAA"
       }
      }
     }
    }
   }
  },
  {
   "label1": "Brown Cow",
   "label2": "Green Frog",
   "differences": {
    "label": {
     "value1": "Brown Cow",
     "value2": "Green Frog"
    }
   }
  }
 ],
 "deleted": [
  {
   "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e95170ZZZ",
   "label": "Red Fish"
  }
 ],
 "added": [
  {
   "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e951709AAA",
   "label": "Blue Bird"
  }
 ]
}
javascript json google-apps-script compare
1个回答
1
投票

这提供了一份抓住了您所要求的精神的报告。输出略有不同

function compareJSONs(oldJSON,newJSON) {

  // Create an object to store the results of the comparison
  let
    results = {
               deleted: [],
               added: [],
               changed: []
              };

  // Loop through the old JSON array
  for (const oldObj of oldJSON) {
    // Find the matching object in the new JSON array
    const newObj = newJSON.find(newItem => newItem.id === oldObj.id);

    if (!newObj) {
      // Object exists in oldJSON but not in newJSON (deleted)
      results.deleted.push(oldObj);
    } 
    else {
      // Compare nested options
      let changedOptions = {};

      for (const key in oldObj.options) {
        if (newObj.options[key] !== oldObj.options[key]) {
          changedOptions[key] = {
            oldValue: oldObj.options[key],
            newValue: newObj.options[key]
          };
        };
      };

      for (const key in newObj.options) {
        //console.log(newObj.options[key])
        if (newObj.options[key] !== oldObj.options[key]) {
          changedOptions[key] = {
            oldValue: oldObj.options[key],
            newValue: newObj.options[key]
          };
        };
      };
    
      //Remove objects where keys have identical value (all the NON-changed options)
      for (const key in changedOptions) {
        const {oldValue: a, newValue: b} = changedOptions[key];
        a?.index === b?.index && a?.value === b?.value && a?.label === b?.label && delete changedOptions[key];
      };

    
      if (Object.keys(changedOptions).length > 0) {
        // Object exists in both oldJSON and newJSON, with changes
        results.changed.push({
            id: newObj.id,
            oldLabel: oldObj.label,
            newLabel: newObj.label,
            changedOptions
        });
      };
    };
  }; 

  // Check for added objects
  for (const newObj of newJSON) {
    if (!oldJSON.find(oldItem => oldItem.id === newObj.id)) {
      results.added.push(newObj);
    };
  };

  return results;
}


console.log("Deleted objects:", JSON.stringify(results.deleted, null,1));
Deleted objects: [
 {
  "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e95170ZZZ",
  "label": "Red Fish"
 }
]

console.log("Added objects:", JSON.stringify(results.added, null,1));
Added objects: [
 {
  "id": "f794c6a52e793ee6f5c42cd5df6b4435236e3495e951709AAA",
  "label": "Blue Bird"
 }
]

console.log("Changed objects:", JSON.stringify(results.changed, null,1));
Changed objects: [
 {
  "id": "c3c6f410f58e5836431b473ebcf134756232d04f2bf35edff8",
  "oldLabel": "Sector2",
  "newLabel": "Sector",
  "changedOptions": {
   "2fe91aa3567c0d04c521dcd2fc7e40d7622bb8c3f594d503da": {
    "oldValue": {
     "index": 1,
     "value": "Student",
     "label": "Student"
    },
    "newValue": {
     "index": 2,
     "value": "Student",
     "label": "Student"
    }
   },
   "c59ea1159f33b91a7f6edc6925be5e373fc543e4": {
    "oldValue": {
     "index": 2,
     "value": "BBB",
     "label": "BBB"
    },
    "newValue": {
     "index": 3,
     "value": "AAA",
     "label": "AAA"
    }
   },
   "c59ea1159f33b91a7f6edc6925be5e373fc54AAA": {
    "oldValue": {
     "index": 3,
     "value": "Orange Duck",
     "label": "Orange Duck"
    }
   },
   "c59ea1159f33b91a7f6edc6925be5e373DDDDDDDDD": {
    "newValue": {
     "index": 1,
     "value": "GrassLand",
     "label": "TreeLand"
    }
   }
  }
 }
]
© www.soinside.com 2019 - 2024. All rights reserved.