You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 12:33:30