轻松:JavaScript 中去除 JSON 数据的实用方法
在处理前端开发或数据交互时,我们经常会与 JSON (JavaScript Object Notation) 数据打交道,从服务器获取的 API 响应、本地存储的配置信息,都常常以 JSON 格式存在,这些原始数据往往并非完美无瑕,可能包含我们不需要的属性、为 null 或 undefined 的值,甚至是空字符串,为了得到干净、可用的数据,我们就需要对这些 JSON 数据进行“去除”或“清理”操作。
本文将详细介绍在 JavaScript 中如何高效地去除 JSON 数据中的冗余信息,涵盖从简单到复杂的多种场景和方法。
核心概念:JSON 与 JavaScript 对象的关系
首先要明确一个关键点:JSON 是一种数据格式,而 JavaScript 对象是数据结构,在 JavaScript 中,我们通常使用 JSON.parse() 将从服务器收到的 JSON 字符串转换为一个 JavaScript 对象,然后对这个对象进行操作。
我们讨论的“去除 JSON 数据”,实际上是指对由 JSON 解析而来的 JavaScript 对象进行操作。
场景一:去除对象中指定的单个或多个属性
这是最常见的需求,比如我们只想保留用户名和邮箱,而需要移除密码、手机号等敏感信息。
方法 1:使用解构赋值 + 剩余运算符 (ES6+,推荐)
这是现代 JavaScript 中最简洁、最优雅的方法,它允许你轻松地“提取”需要的属性,并将剩余的所有属性收集到一个新对象中。
示例代码:
// 原始的 JSON 数据(已解析为 JS 对象)
const originalUser = {
id: 101,
username: 'john_doe',
password: 'a-very-secret-password',
email: 'john.doe@example.com',
phone: '13800138000',
createdAt: '2023-10-27T10:00:00Z'
};
// 使用解构赋值和剩余运算符
const { password, phone, ...cleanedUser } = originalUser;
// cleanedUser 就是一个新对象,不包含 password 和 phone
console.log(cleanedUser);
/*
输出:
{
id: 101,
username: 'john_doe',
email: 'john.doe@example.com',
createdAt: '2023-10-27T10:00:00Z'
}
*/
优点:
- 代码极其简洁,可读性高。
- 只需一行代码就能完成提取和去除。
方法 2:使用 delete 操作符
这是一个比较传统的方法,直接在原对象上删除属性。
示例代码:
const originalUser = { /* ... 同上 ... */ };
// 直接删除属性
delete originalUser.password;
delete originalUser.phone;
// originalUser 对象本身已被修改
console.log(originalUser);
注意:
delete会直接修改原对象,而不是创建一个新对象,在函数式编程或需要保持数据不可变性的场景下,这可能会导致副作用。- 虽然可行,但需要为每个要删除的属性写一行
delete语句,当属性较多时,代码会变得冗长。
场景二:去除对象中所有值为 null、undefined 或空字符串的属性
当我们处理从数据库或第三方 API 获取的数据时,经常会遇到很多空值,这些空值可能会干扰我们的逻辑渲染或数据处理。
方法:使用 Object.entries() 和 Object.fromEntries() (ES6+,推荐)
这是一个非常强大的组合,可以轻松地过滤和转换对象。
示例代码:
const originalData = {
name: 'Alice',
age: null,
email: '',
address: {
street: '123 Main St',
city: undefined
},
isActive: true
};
// 定义一个过滤函数,判断值是否“有效”
const isValueValid = (value) => {
// 排除 null, undefined, 和空字符串
return value !== null && value !== undefined && value !== '';
};
// 1. 将对象转换为 [key, value] 数组
// 2. 使用 filter 方法过滤掉无效的项
// 3. 将过滤后的数组转换回对象
const cleanedData = Object.fromEntries(
Object.entries(originalData).filter(([key, value]) => isValueValid(value))
);
console.log(cleanedData);
/*
输出:
{
name: 'Alice',
address: {
street: '123 Main St',
city: undefined // 注意:address 对象内部的 city 不会被过滤
},
isActive: true
}
*/
进阶:递归去除所有层级的空值
上面的方法只会过滤顶层属性,如果希望递归地过滤对象内部的空值,可以稍微修改一下:
function deepRemoveEmpty(obj) {
// 如果不是对象或数组,直接返回
if (typeof obj !== 'object' || obj === null) {
return obj;
}
// 处理数组
if (Array.isArray(obj)) {
return obj.map(item => deepRemoveEmpty(item)).filter(item => item !== null && item !== undefined && item !== '');
}
// 处理对象
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = deepRemoveEmpty(obj[key]);
// 只有当递归处理后的值有效时,才添加到新对象中
if (value !== null && value !== undefined && value !== '') {
result[key] = value;
}
}
}
return result;
}
const deeplyCleanedData = deepRemoveEmpty(originalData);
console.log(deeplyCleanedData);
/*
输出:
{
name: 'Alice',
address: {
street: '123 Main St'
},
isActive: true
}
*/
场景三:去除对象中值为特定类型的属性
有时我们只想去除值为数字、布尔值或特定对象的属性,这可以通过自定义过滤条件轻松实现。
示例代码:
假设我们想去除所有值为布尔型的属性:
const originalConfig = {
apiEnabled: true,
timeout: 5000,
debugMode: false,
retryCount: 3,
logLevel: 'info'
};
const removeBooleanValues = (obj) => {
return Object.fromEntries(
Object.entries(obj).filter(([key, value]) => typeof value !== 'boolean')
);
};
const configWithoutBooleans = removeBooleanValues(originalConfig);
console.log(configWithoutBooleans);
/*
输出:
{
timeout: 5000,
retryCount: 3,
logLevel: 'info'
}
*/
场景四:去除数组中的重复项
JSON 数据是一个数组,并且数组元素是对象,去除重复项会稍微复杂一些,因为 Set 和 includes 无法直接用于对象。
方法:结合 filter() 和 some()
some() 方法可以检查数组中是否至少有一个元素满足条件,非常适合用来判断是否已经存在某个对象。
示例代码:
const userList = [
{ id: 1, name: 'Bob' },
{ id: 2, name: 'Charlie' },
{ id: 1, name: 'Bob' }, // 重复项
{ id: 3, name: 'David' }
];
// 使用 filter 和 some 去重
const uniqueUsers = userList.filter((user, index, self) =>
// 检查当前用户是否是第一次出现
index === self.findIndex((u) => u.id === user.id)
);
console.log(uniqueUsers);
/*
输出:
[
{ id: 1, name: 'Bob' },
{ id: 2, name: 'Charlie' },
{ id: 3, name: 'David' }
]
*/
原理: self.findIndex(...) 会找到与当前 user.id 相同的第一个元素的索引,如果这个索引和当前元素的 index 相等,说明这是第一次出现,就保留它。
总结与最佳实践
| 场景 | 推荐方法 | 优点 |
|---|---|---|
| 去除指定属性 | 解构赋值 + 剩余运算符 | 代码简洁,可读性高,不修改原对象 |
| 去除空值 | Object.entries + Object.fromEntries |
函数式风格,链式调用,优雅高效 |
| 递归去除空值 | 递归函数 | 逻辑清晰,能处理任意层级的嵌套 |
| 去除特定类型 | Object.entries + filter + 自定义条件 |
灵活,可定制性强 |
| 数组去重 | filter + findIndex |
经典且可靠,适用于对象数组 |
核心建议:
- 优先使用 ES6+ 的新特性:如解构赋值、剩余运算符、
Object.entries()



还没有评论,来说两句吧...