我有两个来自应用程序的 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"
}
]
}
这提供了一份抓住了您所要求的精神的报告。输出略有不同
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"
}
}
}
}
]