
本文详解如何对具有两层嵌套结构的 JSON 数据(如银行机构列表及其下属信用卡产品)进行条件过滤,确保外层结构完整保留,仅对内层 offerCard 数组执行精确匹配,并剔除过滤后为空的中间节点。
本文详解如何对具有两层嵌套结构的 json 数据(如银行机构列表及其下属信用卡产品)进行条件过滤,确保外层结构完整保留,仅对内层 `offercard` 数组执行精确匹配,并剔除过滤后为空的中间节点。
在处理类似金融产品目录这类层级化数据时,常见需求是:按卡片名称(nameCard)或 ID(idCard)搜索,但必须维持原始的“机构 → 卡产品列表”双层结构。直接使用 forEach + 赋值会丢失上下文、无法累积结果;而简单 filter 又无法重建外层对象。正确解法需结合 映射(map)+ 展开(...)+ 二次过滤(filter) 三步策略。
✅ 正确实现逻辑(TypeScript/JavaScript)
const filtroValue = '10'; // 支持字符串或数字输入
const dataFiltered = {
...originalData, // 保留顶层字段(如 OpenClientIndicator)
listTypeCreditOffer: originalData.listTypeCreditOffer
.map(offer => ({
...offer, // 复制当前机构所有字段(companyName, id 等)
offerCard: offer.offerCard.filter(card =>
card.idCard.toString().includes(filtroValue) ||
(card.nameCard || '').toLowerCase().includes(filtroValue.toLowerCase())
)
}))
.filter(offer => offer.offerCard.length > 0) // 移除 offerCard 为空的机构
};? 关键要点解析
- map 替代 forEach:forEach 无返回值,无法构建新数组;map 逐项转换并生成新结构,是重构嵌套数据的基石。
-
展开运算符 ... 的双重作用:
- ...originalData:浅拷贝顶层属性,避免污染原数据;
- ...offer:保留每个机构的原始信息(companyName, id),仅更新 offerCard。
- 内层 filter 精准匹配:支持模糊搜索(.includes())或精确匹配(===),注意对 null/undefined 字段做空值防护(如 (card.nameCard || ''))。
- 外层 filter 清理空节点:若某机构所有卡片均不匹配,则整个该机构对象被剔除,最终结果只含“有匹配卡片”的机构。
⚠️ 常见错误与规避
- ❌ 错误:let cards; ... forEach(... => { cards = ... })
→ forEach 不返回数组,cards 仅保存最后一次循环结果,且无法关联到对应机构。 - ❌ 错误:未对 offerCard.length === 0 的机构做清理
→ 导致返回结构中存在 offerCard: [] 的冗余条目,破坏业务语义。 - ✅ 最佳实践:将过滤逻辑封装为可复用函数,支持动态字段与操作符:
const filterNestedCards = (data, value, fields = ['idCard', 'nameCard']) => ({
...data,
listTypeCreditOffer: data.listTypeCreditOffer
.map(offer => ({
...offer,
offerCard: offer.offerCard.filter(card =>
fields.some(field => {
const val = card[field];
return val != null &&
String(val).toLowerCase().includes(String(value).toLowerCase());
})
)
}))
.filter(offer => offer.offerCard.length > 0)
});此方案兼顾健壮性、可读性与扩展性,适用于任意两层嵌套的“容器-项目”结构,是前端数据过滤的标准化实践。


















