如何获取JSON文件的主结构?嵌套数组对象合并实现求助
Problem Statement
You want to transform a JSON structure to collect all possible properties across any nested level. For arrays, only the first object should be kept, but it needs to incorporate all properties from every element in the array. The value of each property should be the first encountered one (e.g., keep "lmn" for the "dog" property).
Input JSON
[ { "dog": "lmn", "tiger": [ { "bengoltiger": { "height": { "x": 4 } }, "indiantiger": { "paw": "a", "foor": "b" } }, { "bengoltiger": { "width": { "a": 8 } }, "indiantiger": { "b": 3 } } ] }, { "dog": "pqr", "tiger": [ { "bengoltiger": { "width": { "m": 3 } }, "indiantiger": { "paw": "a", "foor": "b" } }, { "bengoltiger": { "height": { "n": 8 } }, "indiantiger": { "b": 3 } } ], "lion": 90 } ]
Expected Output
[ { "dog": "lmn", "tiger": [ { "bengoltiger": { "height": { "x": 4, "n": 8 }, "width": { "a": 8, "m": 3 } }, "indiantiger": { "paw": "a", "foor": "b", "b": 3 } } ], "lion": 90 } ]
Issues with Your Current Code
Your recursive function has a couple of key problems that prevent it from handling nested structures correctly:
- Shallow Merging: When handling arrays, you only merge top-level keys of array elements, but don't recursively merge nested objects (like the
bengoltigerandindiantigerobjects inside thetigerarray). thisBinding: The recursive callthis.consolidateArray(json[0])may not work as expected becausethismight not reference the function itself in all contexts.- No Deep Object Merge: For nested objects, you don't merge properties from later elements into the reference object—you just overwrite or skip them.
Fixed Solution
Here's an updated recursive function that properly handles deep merging of nested objects and arrays, while retaining the first encountered property values:
function consolidateStructure(obj) { // Handle arrays: merge all elements into the first one, then recurse if (Array.isArray(obj)) { if (obj.length === 0) return obj; // Take the first element as the base to retain first values const base = obj[0]; // Iterate over all other elements in the array for (let i = 1; i < obj.length; i++) { mergeObjects(base, obj[i]); } // Recurse into the consolidated base to handle nested structures consolidateStructure(base); // Keep only the first (consolidated) element in the array obj.splice(1); return obj; } // Handle objects: recurse into each value if (typeof obj === 'object' && obj !== null) { for (const key in obj) { if (obj.hasOwnProperty(key)) { consolidateStructure(obj[key]); } } return obj; } // Return primitive values as-is return obj; } function mergeObjects(target, source) { // Merge properties from source into target, keeping target's values if key exists for (const key in source) { if (source.hasOwnProperty(key)) { const targetVal = target[key]; const sourceVal = source[key]; // If both are objects (not arrays), merge them recursively if (typeof targetVal === 'object' && targetVal !== null && typeof sourceVal === 'object' && sourceVal !== null && !Array.isArray(targetVal) && !Array.isArray(sourceVal)) { mergeObjects(targetVal, sourceVal); } // If target doesn't have the key, add it with source's value else if (!target.hasOwnProperty(key)) { target[key] = sourceVal; } // If target already has the key, do nothing (retain first value) } } } // Test the function with your JSON const json = [ { "dog": "lmn", "tiger": [ { "bengoltiger": { "height": { "x": 4 } }, "indiantiger": { "paw": "a", "foor": "b" } }, { "bengoltiger": { "width": { "a": 8 } }, "indiantiger": { "b": 3 } } ] }, { "dog": "pqr", "tiger": [ { "bengoltiger": { "width": { "m": 3 } }, "indiantiger": { "paw": "a", "foor": "b" } }, { "bengoltiger": { "height": { "n": 8 } }, "indiantiger": { "b": 3 } } ], "lion": 90 } ]; consolidateStructure(json); console.log(JSON.stringify(json, null, 2));
How It Works
consolidateStructure: This function handles arrays and objects recursively:- For arrays, it takes the first element as the base, merges all other elements into this base using
mergeObjects, then recurses into the base to handle nested structures, and finally trims the array to only keep the consolidated first element. - For objects, it recurses into each property value to process nested arrays/objects.
- For arrays, it takes the first element as the base, merges all other elements into this base using
mergeObjects: This helper function deeply merges properties from the source object into the target object. It retains the target's values (first encountered) if the key already exists, and adds new keys from the source if they're missing in the target. For nested objects, it calls itself recursively to merge their properties.
Running this code will produce exactly your expected output.
内容的提问来源于stack exchange,提问作者Kaustubh Badrike

