如何移除JSON中的空白字段?现有代码问题及优化需求
问题排查与解决方案
咱们先把原代码里的问题一个个揪出来,再给出修复后的版本,最后实现不修改原对象的清理逻辑。
一、原代码的核心问题
你的代码里有好几处关键错误,导致空对象/数组没法被移除:
- 函数名拼写错误:你定义了判断空白的函数
isBlank,但递归时却用了isEmpty,这直接导致判断逻辑完全失效。 - 变量名笔误:
jsonInput[key_field]里的key_field是个未定义的变量,应该写成jsonInput[key]。 - 空对象判断逻辑缺失:原
isBlank函数里,对象没有length属性,所以val.length === 0对空对象会返回false,根本识别不了空对象。 - 递归后未校验空值:就算递归清理了子对象里的空白字段,原代码也没检查清理后的子对象/数组是不是变成空的了,所以空的
allBlanks数组、att2对象才会留在结果里。 - 数组元素处理遗漏:原代码没考虑数组里的元素清理,比如数组里的空对象应该被移除,而不是留在数组里变成
[{ }]。
二、修复修改原对象的版本
先完善空白判断函数,再修正递归逻辑,处理数组和对象的所有情况:
// 完善空白字段判断:覆盖null、空白字符串、空数组、空对象 const isBlank = (val) => { if (val === null) return true; if (typeof val === 'string') return val.trim().length === 0; if (Array.isArray(val)) return val.length === 0; if (typeof val === 'object') return Object.keys(val).length === 0; return false; }; function clean(jsonInput) { // 先处理数组:从后往前删,避免索引错乱 if (Array.isArray(jsonInput)) { for (let i = jsonInput.length - 1; i >= 0; i--) { const item = jsonInput[i]; if (typeof item === 'object' && item !== null) { clean(item); // 递归后如果元素变成空白,直接移除 if (isBlank(item)) { jsonInput.splice(i, 1); } } else if (isBlank(item)) { jsonInput.splice(i, 1); } } return; } // 处理对象:遍历所有键,递归清理后再判断是否删除 Object.keys(jsonInput).forEach(key => { const val = jsonInput[key]; if (typeof val === 'object' && val !== null) { clean(val); // 子对象/数组清理后变空白,删除这个键 if (isBlank(val)) { delete jsonInput[key]; } } else if (isBlank(val)) { delete jsonInput[key]; } }); }
测试这段代码,传入你的输入数据,就能得到预期的输出:
const input = { "print": "notBlank", "this": "notBlank", "example": "notBlank", "blank": null, "allBlanks": [ { "from": "", "blank0": null } ], "att2": { "blank1": "", "blank2": [] }, "att3": { "one": "1", "two": "2", "three": "3", "blank3": " " } }; clean(input); console.log(JSON.stringify(input, null, 2)); // 输出和预期完全一致
三、不修改原对象,生成副本的版本
如果不想改动原数据,我们可以创建一个新的对象/数组,递归处理每个元素,只保留非空白内容:
const isBlank = (val) => { if (val === null) return true; if (typeof val === 'string') return val.trim().length === 0; if (Array.isArray(val)) return val.length === 0; if (typeof val === 'object') return Object.keys(val).length === 0; return false; }; function cleanCopy(jsonInput) { // 处理数组:先递归处理每个元素,再过滤空白项 if (Array.isArray(jsonInput)) { return jsonInput .map(item => typeof item === 'object' && item !== null ? cleanCopy(item) : item) .filter(item => !isBlank(item)); } // 处理对象:创建新对象,只保留清理后非空白的键值对 if (typeof jsonInput === 'object' && jsonInput !== null) { const cleanedObj = {}; Object.keys(jsonInput).forEach(key => { const val = jsonInput[key]; const cleanedVal = typeof val === 'object' && val !== null ? cleanCopy(val) : val; if (!isBlank(cleanedVal)) { cleanedObj[key] = cleanedVal; } }); return cleanedObj; } // 非对象/数组类型直接返回 return jsonInput; }
使用这个版本时,原对象会完全保留,返回的是全新的清理后的数据:
const input = { /* 你的输入数据 */ }; const cleanedResult = cleanCopy(input); // input 保持不变,cleanedResult 是预期的输出
为什么这样改?
- 完善后的
isBlank函数覆盖了所有你定义的空白字段类型,不会漏掉空对象。 - 处理数组时从后往前删除元素,避免因为索引变化导致的漏删。
- 副本版本通过
map和filter处理数组,通过创建新对象处理对象,完全没有副作用,适合需要保留原数据的场景。
内容的提问来源于stack exchange,提问作者lokilindo
相关产品推荐
相关产品推荐

