讲师中心 微信公众号

工具推荐

视频效率加速
剧云
剧云

中文短剧剧本制作平台

Seko
Seko

AI短剧一键生成成片

立刻MV
立刻MV

低成本歌曲 MV、视频生成

AniShort
AniShort

AI短剧协同制作平台

JavaScript中基于不同键路径合并复杂JSON数据

胖杰吖_7759

胖杰吖_7759

发布时间:2025-10-01 12:08:01

|

585人浏览过

|

来源于php中文网

原创

JavaScript中基于不同键路径合并复杂JSON数据

本教程详细讲解如何在JavaScript中合并一个包含复杂JSON对象的数组。面对键(key)可能存在于顶层或嵌套结构(如confidential.key)中的情况,我们将演示如何利用Array.prototype.reduce方法高效地将具有相同键的所有相关信息合并成一个单一的对象,从而生成结构清晰、统一的数据集。

问题描述与目标

在处理异构数据时,我们经常会遇到需要根据某个共同标识符(key)来合并不同数据片段的场景。本教程所面临的问题是:给定一个包含多个json对象的数组,这些对象可能在顶层拥有一个key字段,也可能在一个嵌套的confidential对象中包含key字段(即confidential.key)。我们的目标是将所有具有相同key值的对象合并成一个单一的、更完整的对象。

原始数据示例:

[
  {
    "key": 111,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ]
  },
  {
    "key": 222,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ]
  },
  {
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 111
    }
  },
  {
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 222
    }
  }
]

期望的合并结果:

[
  {
    "key": 111,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ],
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 111
    }
  },
  {
    "key": 222,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ],
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 222
    }
  }
]

可以看到,key为111和222的两个对象都被成功合并,其studentInfo和confidential属性被整合到同一个对象中。

核心合并策略

为了实现上述合并目标,我们可以采用Array.prototype.reduce方法。reduce方法遍历数组中的每个元素,并将其合并到单个累加器值中。在这个场景下,累加器将是一个数组,用于存放最终合并后的对象。

立即学习“Java免费学习笔记(深入)”;

核心思路如下:

  1. 初始化一个空数组作为reduce的累加器,它将存储最终合并后的对象。
  2. 遍历输入数组中的每个对象。
  3. 判断当前对象的键路径:
    • 如果当前对象包含顶层key属性,说明它可能是某个合并组的“主”对象,或者至少是该组的第一个出现对象。此时,我们直接将此对象添加到累加器数组中。
    • 如果当前对象不包含顶层key,但包含confidential.key属性,则说明它是一个补充信息对象。我们需要根据confidential.key的值,在累加器数组中查找是否存在一个已经存在的、具有相同key值的对象。
  4. 执行合并操作:
    • 如果找到了匹配的对象,则将当前对象的属性合并到已找到的对象中。Object.assign()方法非常适合这种浅层合并。
    • 如果没有找到匹配的对象,这通常意味着数据结构可能不符合预期,或者需要将此对象作为新的合并组的起始。在我们的场景中,由于key是唯一的标识符,我们假设所有confidential对象都有对应的顶层key对象。

JavaScript 实现

以下是使用JavaScript实现上述合并逻辑的代码:

const inputData = [
  {
    key: 111,
    studentInfo: [
      {
        details: {
          calculated_fields: null,
          status: false,
        },
      },
    ],
  },
  {
    key: 222,
    studentInfo: [
      {
        details: {
          calculated_fields: null,
          status: false,
        },
      },
    ],
  },
  {
    confidential: {
      data: {
        access_control: {
          private_data: null,
          users: [],
        },
      },
      key: 111,
    },
  },
  {
    confidential: {
      data: {
        access_control: {
          private_data: null,
          users: [],
        },
      },
      key: 222,
    },
  },
];

// 使用 reduce 方法进行数据合并
const mergedData = inputData.reduce((accumulator, currentObject) => {
  // 如果当前对象包含顶层 'key' 属性
  if (currentObject.key) {
    // 直接将此对象推入累加器数组
    accumulator.push(currentObject);
  } else if (currentObject.confidential && currentObject.confidential.key) {
    // 如果当前对象包含 'confidential.key' 属性
    const targetKey = currentObject.confidential.key;
    // 在累加器中查找是否存在与 targetKey 匹配的对象
    const existingObject = accumulator.find((obj) => obj.key === targetKey);

    // 如果找到了匹配的对象,则进行合并
    if (existingObject) {
      // 使用 Object.assign 将 currentObject 的属性合并到 existingObject 中
      // 注意:这里是浅合并,如果内部对象也需要深度合并,则需要更复杂的逻辑
      Object.assign(existingObject, currentObject);
    } else {
      // 如果没有找到匹配的对象,这可能意味着数据结构不完整或顺序不符合预期
      // 根据实际业务需求,可以选择抛出错误、记录日志或将其作为一个新对象加入
      // 在本例中,我们假设所有 confidential 对象都有对应的顶层 key 对象
      console.warn(`Warning: No matching object found for key ${targetKey} in accumulator.`);
    }
  }
  return accumulator; // 返回更新后的累加器
}, []); // 初始累加器是一个空数组

console.log(JSON.stringify(mergedData, null, 2));

代码逻辑详解

  1. inputData.reduce((accumulator, currentObject) => { ... }, []);:

    • reduce方法被调用在inputData数组上。
    • accumulator:累加器,这里是一个空数组[],它将逐步构建最终的合并结果。
    • currentObject:inputData数组中当前正在处理的对象。
    • []:reduce方法的第二个参数,表示accumulator的初始值。
  2. if (currentObject.key):

    • 检查当前对象是否直接拥有key属性。
    • 如果存在,说明这是一个带有主要标识符的对象(如包含studentInfo的对象),将其直接推入accumulator。这是合并组的起点。
  3. else if (currentObject.confidential && currentObject.confidential.key):

    • 如果当前对象没有顶层key,则检查它是否包含confidential属性,并且confidential内部是否含有key。
    • targetKey = currentObject.confidential.key;:提取出嵌套的key值。
  4. const existingObject = accumulator.find((obj) => obj.key === targetKey);:

    Expanso yaml-to-json
    Expanso yaml-to-json

    使用 Expanso Edge 管道将 YAML 输入转换为 JSON 格式。

    下载
    • 使用find方法在accumulator(目前已合并的对象数组)中查找是否存在一个对象的key与targetKey匹配。
  5. if (existingObject) { Object.assign(existingObject, currentObject); }:

    • 如果find方法找到了匹配的existingObject,则使用Object.assign()方法将currentObject的所有可枚举属性复制到existingObject上。
    • Object.assign执行的是浅合并。这意味着如果currentObject和existingObject有同名的非原始类型属性(如对象或数组),currentObject的属性会完全替换existingObject的属性,而不是合并其内部内容。对于本例,confidential对象替换了existingObject中可能存在的同名属性,这符合预期。
  6. return accumulator;:

    • 在每次迭代结束时,reduce回调函数必须返回更新后的accumulator,以便在下一次迭代中使用。

注意事项与扩展

  1. 键的唯一性与存在性:

    • 本解决方案依赖于key或confidential.key的准确存在和唯一性。在实际应用中,应考虑这些键可能缺失、为null或重复的情况,并增加相应的错误处理或默认值逻辑。
    • 例如,可以使用可选链操作符 currentObject.confidential?.key 来更安全地访问嵌套属性。
  2. 合并深度:

    • Object.assign()执行的是浅合并。如果studentInfo或confidential内部的数组或对象也需要深度合并(例如,合并studentInfo数组中的元素,而不是替换整个studentInfo数组),则需要自定义一个深度合并函数,或者使用如Lodash的_.merge等工具库。
    • 对于本教程的示例,浅合并是符合期望的。
  3. 性能考量:

    • 在reduce回调中,accumulator.find()操作在最坏情况下需要遍历整个accumulator数组。如果inputData非常大,并且accumulator也变得非常大,这可能导致O(N^2)的性能开销。

    • 优化建议:对于大规模数据,可以考虑先将数据转换为以key为键的Map或普通对象,以实现O(1)的查找效率,从而将整体复杂度优化到O(N)。

      const optimizedMergedData = inputData.reduce((map, currentObject) => {
        const key = currentObject.key || currentObject.confidential?.key;
        if (key) {
          map.set(key, { ...(map.get(key) || {}), ...currentObject });
        }
        return map;
      }, new Map());
      
      const finalResult = Array.from(optimizedMergedData.values());
      console.log(JSON.stringify(finalResult, null, 2));

      这种优化方案在处理大量数据时会显著提高性能。

  4. 数据顺序:

    • 本解决方案假定带有顶层key的对象会先于或与带有confidential.key的对象一起出现,并且find操作能找到它。如果confidential对象先于其对应的顶层key对象出现,那么find将失败,导致数据丢失或错误。确保数据输入顺序或调整逻辑以处理乱序情况是重要的。本教程的原始数据示例是“顶层key对象在前,confidential对象在后”,因此当前的find逻辑是有效的。

通过以上方法,我们可以灵活高效地处理JSON数据中基于不同键路径的合并需求,生成结构统一、内容完整的数据集。

热门AI工具

更多
讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2315

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3802

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1256

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

4399

2025.09.10

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

569

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

17740

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1243

2024.02.23

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

80

2026.11.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WebStorm 官方调试文档
WebStorm 官方调试文档

共0课时 | 0人学习

React 教程
React 教程

共58课时 | 12.5万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 6.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn