如何展开嵌套对象中重复出现的包裹属性?
data Layers & Collapsing Single-Element Arrays Hey there! Let's tackle this problem step by step—first with the robust, standard recursive solution you're looking for, then we'll talk about that regex idea you had and its pros and cons.
1. Recursive Approach (The Standard, Reliable Solution)
This is the go-to method here because it gracefully handles any nesting depth and gives you full control over the optional array-collapsing logic. The core idea is to traverse every part of your object/array, unwrap any data wrappers we find, and collapse arrays with only one item if we want to.
Here's the implementation:
function unwrapData(obj, collapseSingleArrays = true) { // Handle arrays first: process each element, then check if we need to collapse if (Array.isArray(obj)) { const processedItems = obj.map(item => unwrapData(item, collapseSingleArrays)); return collapseSingleArrays && processedItems.length === 1 ? processedItems[0] : processedItems; } // Handle objects: check if it's a pure `data` wrapper, otherwise process each key if (typeof obj === 'object' && obj !== null) { // If this object only has a `data` key, unwrap it immediately if (Object.keys(obj).length === 1 && obj.hasOwnProperty('data')) { return unwrapData(obj.data, collapseSingleArrays); } // For regular objects, process each key-value pair recursively const cleanedObj = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { cleanedObj[key] = unwrapData(obj[key], collapseSingleArrays); } } return cleanedObj; } // Return primitive values (strings, numbers, etc.) as-is return obj; }
Testing It Out
Let's run this against your test object:
const testObj = { data: { Name: 'Likert Scale', Header_Text: [ { data: { Content_Type: 'Do you agree or disagree with the statement?', Text: 'Do you agree or disagree with the statement?\n', }, }, ], Possible_Answers: [ { data: { Content_Type: 'Strongly Agree', Text: 'Strongly Agree\n\n', }, }, { data: { Content_Type: 'Strongly Disagree', Text: 'Strongly Disagree\n', }, }, ], }, }; const desiredObj = unwrapData(testObj); console.log(JSON.stringify(desiredObj, null, 2));
This will output exactly the structure you're aiming for! You can also disable the array-collapsing by passing false as the second argument if you ever need to keep single-element arrays.
2. Regex Approach (Not Recommended for Production)
Your idea of converting the object to JSON and using regex is clever for quick one-off tasks, but it's not sustainable for production use. Here's why:
- Regex can't reliably parse nested JSON structures—if a string value happens to contain something like
"data":, it'll get incorrectly replaced. - It can't handle escaped characters in JSON (e.g., a string like
"He said \"data\" is redundant"will break the regex). - Complex nested layers will require increasingly convoluted regex patterns that are hard to debug and maintain.
If you still want to try it for simple cases, here's a basic version:
function unwrapWithRegex(obj, collapseSingleArrays = true) { let jsonStr = JSON.stringify(obj); // Replace {"data": ...} with the inner object jsonStr = jsonStr.replace(/"data":(\s*\{[^}]*\})/g, '$1'); // Optional: Collapse single-element arrays if (collapseSingleArrays) { jsonStr = jsonStr.replace(/\[(\s*\{[^}]*\}\s*)\]/g, '$1'); } return JSON.parse(jsonStr); }
But again—this will fail on more complex inputs, so stick with the recursive method for anything that needs to be reliable.
Final Thoughts
The recursive approach is hands down the best choice here. It's flexible, handles all edge cases (like null values, empty objects/arrays), and is easy to tweak if your API structure changes slightly. The regex method is a quick hack at best, but it won't hold up over time.
内容的提问来源于stack exchange,提问作者ParthianShotgun

