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

扁平化嵌套JSON时如何保留键名以实现反向嵌套?

保留嵌套JSON扁平化后的父级键名,实现可还原的扁平化方案

我明白你现在的核心需求:既要把嵌套的JSON结构扁平化,又要保留完整的父级键路径,这样后续还能顺利还原回原始的嵌套格式。其实这个思路很清晰——在扁平化的过程中跟踪每一层的键名,用一个约定的分隔符(比如你示例里的#)把路径拼接起来就行。下面给你具体的实现方案:


问题回顾

你有一套特殊的嵌套JSON结构:每一层的键对应一个包含dataType、value、someKey的数组;当dataType为Object时,value里又是重复的嵌套结构。当前的扁平化操作丢失了父级键(比如firstLevelKey2、secondLevelKey2),你需要生成类似firstLevelKey2#secondLevelKey2#thirdLevelKey1这样的完整路径键名,保证可还原。

原始嵌套结构

[
  {
    firstLevelKey1 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }]
  },
  {
    firstLevelKey2:[{ dataType : 'Object' },{ value : [{
      secondLevelKey1 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }]
    },{
      secondLevelKey2 : [{ dataType : 'Object' },{ value : [{
        thirdLevelKey1:[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }]
      },{
        thirdLevelKey2 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }]
      },{
        thirdLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }]
      }]
    },{ someKey : 'someValue' }]
    },{
      secondLevelKey3 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }]
    }]
  },{ someKey : 'someValue' }]
  },
  {
    firstLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }]
  }
]

实现思路与代码

核心逻辑是递归遍历+维护键路径:

  1. 遍历顶层数组的每个对象,提取根键作为初始路径
  2. 对每个键对应的数组,提取dataType和value项
  3. 如果dataType是String,直接把完整路径作为键,将数组加入结果
  4. 如果dataType是Object,递归处理value里的嵌套对象,拼接父路径与当前键

JavaScript实现代码

function flattenWithPath(nestedArray) {
  const result = [];

  // 递归处理每一层对象,parentPath记录当前的父级键路径
  function processItem(item, parentPath = '') {
    // 每个对象只有一个键,直接提取
    const currentKey = Object.keys(item)[0];
    const currentData = item[currentKey];
    
    // 从数组中提取dataType、value、someKey对应的对象
    const dataTypeObj = currentData.find(obj => obj.dataType);
    const valueObj = currentData.find(obj => obj.value);
    const someKeyObj = currentData.find(obj => obj.someKey);

    // 拼接当前完整路径
    const fullPath = parentPath ? `${parentPath}#${currentKey}` : currentKey;

    if (dataTypeObj?.dataType === 'Object') {
      // 递归处理Object类型下的所有嵌套对象
      valueObj.value.forEach(nestedItem => {
        processItem(nestedItem, fullPath);
      });
    } else {
      // String类型直接加入结果数组
      result.push({
        [fullPath]: [dataTypeObj, valueObj, someKeyObj]
      });
    }
  }

  // 遍历顶层数组的每个对象
  nestedArray.forEach(item => processItem(item));
  return result;
}

// 测试原始数据
const originalData = [/* 这里放入你原始的嵌套数据 */];
const flattenedResult = flattenWithPath(originalData);
console.log(JSON.stringify(flattenedResult, null, 2));

运行结果(符合你的期望)

[
  {
    "firstLevelKey1": [
      { "dataType": "String" },
      { "value": "someString" },
      { "someKey": "someValue" }
    ]
  },
  {
    "firstLevelKey2#secondLevelKey1": [
      { "dataType": "String" },
      { "value": "someString" },
      { "someKey": "someValue" }
    ]
  },
  {
    "firstLevelKey2#secondLevelKey2#thirdLevelKey1": [
      { "dataType": "String" },
      { "value": "someString" },
      { "someKey": "someValue" }
    ]
  },
  {
    "firstLevelKey2#secondLevelKey2#thirdLevelKey2": [
      { "dataType": "String" },
      { "value": "someString" },
      { "someKey": "someValue" }
    ]
  },
  {
    "firstLevelKey2#secondLevelKey2#thirdLevelKey3": [
      { "dataType": "String" },
      { "value": "someString" },
      { "someKey": "someValue" }
    ]
  },
  {
    "firstLevelKey2#secondLevelKey3": [
      { "dataType": "String" },
      { "value": "someString" },
      { "someKey": "someValue" }
    ]
  },
  {
    "firstLevelKey3": [
      { "dataType": "String" },
      { "value": "someString" },
      { "someKey": "someValue" }
    ]
  }
]

额外:还原嵌套结构的思路

如果之后需要把扁平化的数据还原回原始嵌套格式,只需要按#拆分键路径,逐层构建嵌套对象即可:

function restoreFromFlattened(flattenedArray) {
  const result = [];

  flattenedArray.forEach(item => {
    const fullPath = Object.keys(item)[0];
    const data = item[fullPath];
    const pathParts = fullPath.split('#');
    
    // 从最内层开始反向构建对象
    let currentObj = { [pathParts.pop()]: data };
    
    // 逐层向外嵌套,补充Object类型的结构
    while (pathParts.length > 0) {
      const key = pathParts.pop();
      currentObj = {
        [key]: [
          { dataType: 'Object' },
          { value: [currentObj] },
          { someKey: data.find(obj => obj.someKey).someKey }
        ]
      };
    }
    
    result.push(currentObj);
  });

  return result;
}

// 测试还原
const restoredData = restoreFromFlattened(flattenedResult);

内容的提问来源于stack exchange,提问作者Manoj HT

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:40:50