Snowflake中如何实现嵌套JSON的深度合并
嵌套对象深合并实现方案
Object.assign 属于浅合并API,仅会遍历对象的一级可枚举属性做覆盖赋值,遇到值为对象的嵌套属性时,会直接用源对象的该属性整体替换目标对象的同key属性,不会递归合并内部字段,这也是直接用它处理示例代码时,location下的country字段会丢失的根本原因。
注:你给出的预期输出中name字段值标注为Liya属于笔误,按照传入的updates配置,合并后name字段值应为David。
方案1:手写递归深合并(无第三方依赖)
核心逻辑是遍历所有待合并对象的属性,当目标值和源值同为纯对象时,递归执行合并逻辑,其余类型直接做赋值覆盖即可:
function deepMerge(target, ...sources) { if (typeof target !== 'object' || target === null) target = {} sources.forEach(source => { if (typeof source !== 'object' || source === null) return Object.keys(source).forEach(key => { const targetVal = target[key] const sourceVal = source[key] // 双方同key值均为非数组对象时递归合并 if ( typeof targetVal === 'object' && targetVal !== null && typeof sourceVal === 'object' && sourceVal !== null && !Array.isArray(targetVal) && !Array.isArray(sourceVal) ) { target[key] = deepMerge(targetVal, sourceVal) } else { target[key] = sourceVal } }) }) return target } // 测试示例 const user = { name: "Liya", phone: 12345, location: { city: "Camden", country: "UK" } }; const updates = { name: "David", phone: 12345678, location: { city: "Smithfield" } }; const mergedResult = deepMerge({}, user, updates) console.log(mergedResult) /* 输出结果: { name: 'David', phone: 12345678, location: { city: 'Smithfield', country: 'UK' } } */
你可以根据自己的业务需求调整逻辑:如果需要合并数组,可以去掉判断里的数组校验,或者自定义数组合并规则(比如去重、按下标合并等)。
方案2:使用Lodash的_.merge方法
如果项目中已经引入了Lodash工具库,可以直接使用内置的深合并方法,它已经处理了循环引用、数组合并等大部分边界场景,不需要自己手写递归:
import _ from 'lodash' const mergedResult = _.merge({}, user, updates)
避坑提醒
- 不要使用对象展开运算符
...处理嵌套对象合并,它的合并逻辑和Object.assign完全一致,属于浅合并,嵌套字段会被整体覆盖。 - 不要试图通过
JSON.parse(JSON.stringify())绕路实现合并,这个方案会丢失函数、undefined、Date等特殊类型的值,性能也更差。
内容的提问来源于stack exchange,提问作者Liya
相关产品推荐
相关产品推荐

