javascript数组对象去重需先将嵌套结构序列化或深度比对:json.stringify适用于纯净数据但受键序影响;lodash isequal可语义去重但性能为o(n²);fast-json-stable-stringify能标准化键序提升一致性。

JavaScript 数组去重本身不直接处理“无限嵌套的 JSON 串”,因为 JSON 是字符串,不是对象或数组;但你真正想做的,很可能是:对包含深层嵌套对象/数组的结构化数据(比如解析后的 JSON 对象)组成的数组,进行基于内容的去重。这需要两个关键步骤:一是将嵌套结构可比较(即序列化或深度比对),二是用该依据过滤重复项。
先明确:JSON 字符串 ≠ 可直接去重的数据
如果你手头是多个 JSON 字符串(例如 '{"a":1,"b":[2,3]}'),且想按内容去重,必须先 JSON.parse() 成对象,再深度比较;否则直接比字符串,哪怕语义相同、空格/键序不同也会判为不同(如 '{"a":1}' 和 '{ "a" : 1 }')。
方案一:JSON.stringify + 简单序列化(适合无函数、无 undefined、无循环引用)
这是最常用、轻量的方式,前提是数据纯净:
- 所有值都是 JSON-safe 类型(不包含
undefined、function、Symbol、BigInt、Date、RegExp等) - 对象键顺序一致(或你接受
JSON.stringify({a:1,b:2}) !== JSON.stringify({b:2,a:1})) - 没有循环引用(否则会报错)
示例:
const arr = [
{ a: 1, b: [2, 3] },
{ b: [2, 3], a: 1 }, // 键序不同 → stringify 后不同 → 去重失败
{ a: 1, b: [2, 3] }
];
const seen = new Set();
const unique = arr.filter(item => {
const key = JSON.stringify(item);
if (seen.has(key)) return false;
seen.add(key);
return true;
});
// 注意:结果仍含第 1 和第 2 项(因键序差异),非语义去重
方案二:深度相等比较(推荐用于真正嵌套、需语义去重)
使用 _.isEqual(Lodash)或手写深度比对函数,能正确识别结构等价对象(忽略键序、处理数组/对象嵌套):
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 安装 Lodash:
npm install lodash,然后import { isEqual } from 'lodash'; - 手动实现简易 deepEqual 也可,但需谨慎处理循环引用、Date、NaN 等边界
示例(用 Lodash):
import { isEqual } from 'lodash';
const arr = [
{ a: 1, b: [2, 3] },
{ b: [2, 3], a: 1 }, // 语义相同
{ a: 1, b: [2, 3], c: null }
];
const unique = arr.filter((item, index) =>
index === arr.findIndex(other => isEqual(item, other))
);
⚠️ 注意:findIndex + isEqual 时间复杂度 O(n²),大数据量时较慢;可配合 Map 缓存哈希(如用 fast-deep-equal 库生成稳定 hash)优化。
方案三:预处理 + 标准化键序(解决 stringify 键序问题)
若坚持用 JSON.stringify 但要语义一致,可先标准化对象键顺序:
- 递归遍历对象,对每个对象的键排序后再序列化
- 可用库如
fast-json-stable-stringify(自动排序键、处理循环引用)
示例:
import { stringify } from 'fast-json-stable-stringify';
const arr = [
{ b: [2, 3], a: 1 },
{ a: 1, b: [2, 3] }
];
const seen = new Set();
const unique = arr.filter(item => {
const key = stringify(item); // 两者 key 相同
if (seen.has(key)) return false;
seen.add(key);
return true;
});
不复杂但容易忽略:所谓“无限嵌套”在实际中并不存在(JS 对象嵌套深度有限,V8 约 10000 层),重点在于是否含循环引用——遇到它,任何 JSON 方法都会崩溃,必须用带循环检测的深比较或序列化库。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










