【问题标题】:How do I flatten JSON nested objects while retaining the internal {} in Nodejs?如何在 Nodejs 中保留内部 {} 的同时展平 JSON 嵌套对象?
【发布时间】:2020-04-27 05:23:31
【问题描述】:

这是来自 API 的原始响应。

 {
  result: [
    {
      activeFrom: '2018-02-15T16:02:20.003Z',
      activeTo: '2018-02-15T16:02:20.003Z',
      distance: 0,
      duration: '00:00:00',
      rule: [Object],
      device: [Object],
      diagnostic: [Object],
      driver: 'UnknownDriverId',
      version: '00000000000061b9',
      id: 'a30M9pPNZSEq7DgUdYrF8xw'
    },
    {
      activeFrom: '2018-02-15T16:06:03.003Z',
      activeTo: '2018-02-15T16:06:03.003Z',
      distance: 0,
      duration: '00:00:00',
      rule: [Object],
      device: [Object],
      diagnostic: [Object],
      driver: 'UnknownDriverId',
      version: '00000000000061bb',
      id: 'apk5czda9o06cwRzkSl4_dQ'
    }
  ],
  jsonrpc: '2.0',
  id: 0
}

我正在使用 npm_flat 扁平化 JSON API 响应。它正在产生这个输出。

var json = JSON.parse(request.responseText);
                  json = json.result
                  var json2 = flatten([json], { maxDepth: 15 });
                  console.log("API Response ", json2);

{
  '0.0.activeFrom': '2018-02-15T16:02:20.003Z',
  '0.0.activeTo': '2018-02-15T16:02:20.003Z',
  '0.0.distance': 0,
  '0.0.duration': '00:00:00',
  '0.0.rule.id': 'RuleUnauthorizedDeviceRemovalId',
  '0.0.device.id': 'b1',
  '0.0.diagnostic.id': 'DiagnosticDeviceHasBeenUnpluggedId',
  '0.0.driver': 'UnknownDriverId',
  '0.0.version': '00000000000061b9',
  '0.0.id': 'a30M9pPNZSEq7DgUdYrF8xw',
  '0.1.activeFrom': '2018-02-15T16:06:03.003Z',
  '0.1.activeTo': '2018-02-15T16:06:03.003Z',
  '0.1.distance': 0,
  '0.1.duration': '00:00:00',
  '0.1.rule.id': 'RuleUnauthorizedDeviceRemovalId',
  '0.1.device.id': 'b1',
  '0.1.diagnostic.id': 'DiagnosticDeviceHasBeenUnpluggedId',
  '0.1.driver': 'UnknownDriverId',
  '0.1.version': '00000000000061bb',
  '0.1.id': 'apk5czda9o06cwRzkSl4_dQ'
}

我希望将输出展平在 {} 括号内,但保持它们完整,以便它们可以作为“行”插入 BigQuery。

我也很难摆脱引领我的钥匙的数字(0.0.)。我从研究中尝试了很多代码,但我缺乏实现这一目标的 JS 知识。非常感谢任何意见或解决方案。

所需的输出:

{
  'activeFrom': '2018-02-15T16:02:20.003Z',
  'activeTo': '2018-02-15T16:02:20.003Z',
  'distance': 0,
  'duration': '00:00:00',
  'rule.id': 'RuleUnauthorizedDeviceRemovalId',
  'device.id': 'b1',
  'diagnostic.id': 'DiagnosticDeviceHasBeenUnpluggedId',
  'driver': 'UnknownDriverId',
  'version': '00000000000061b9',
  'id': 'a30M9pPNZSEq7DgUdYrF8xw',
},
{
  'activeFrom': '2018-02-15T16:06:03.003Z',
  'activeTo': '2018-02-15T16:06:03.003Z',
  'distance': 0,
  'duration': '00:00:00',
  'rule.id': 'RuleUnauthorizedDeviceRemovalId',
  'device.id': 'b1',
  'diagnostic.id': 'DiagnosticDeviceHasBeenUnpluggedId',
  'driver': 'UnknownDriverId',
  'version': '00000000000061bb',
  'id': 'apk5czda9o06cwRzkSl4_dQ'
}

【问题讨论】:

  • 您的问题似乎令人困惑。当您想将对象数组用作行输入时,为什么要展平对象数组?只需循环结果数组并将每个对象用作行输入。如果我误解了这个问题,请纠正我。
  • 我正在展平数组以生成 JSON 架构文件以提供给我的 BigQuery 表。我已成功将记录上传到 Bigquery,但我遇到了 REPEATED 列(父列的子列)的问题。一些唯一键可以是值,而具有相同键的其他响应包含嵌套对象,这会导致插入数据出现问题。我想如果我能把它全部弄平,它会解决我的问题。
  • 您知道 JSON 中对象的深度/复杂性吗?如,你能有 diagnostic.moredata.something 吗?还是只有一层?
  • 一些响应嵌套了 7 或 8 层。我愿意将列设置为 a.b.c.d.e.f.... 如果需要只是开始将一些数据放入表中。
  • @Bryan 原谅我的无知,但你介意给我关于如何在我的示例中使用该代码的要点。我一直在努力让它工作,但似乎无法弄清楚。

标签: javascript arrays node.js json


【解决方案1】:

这应该可行:

let totalResult = []

function formatter(obj) {
    let tempResult = {};
    function format(obj, position) {
        for(let key in obj) {
            let val = obj[key];
            let newKey = (position ? position + "." + key : key);
            if(val && typeof val === "object") {
                format(val, newKey);
            } else {
                tempResult[newKey] = val;
            }
        }
    };
    format(obj);
    return tempResult;
}

// your example data has no name. Let's pretend it's called "testData"
for (let i = 0; i < testData.result.length; i++) {
    totalResult.push(formatter(testData.result[i]));
}

// totalResult now contains your formatted data

【讨论】:

  • 非常感谢,这按预期工作!一题。似乎为 .id 键添加引号? [ { activeFrom:'2018-02-15T16:02:20.003Z',activeTo:'2018-02-15T16:02:20.003Z',距离:0,持续时间:'00:00:00','rule.id ':'RuleUnauthorizedDeviceRemovalId','device.id':'b1','diagnostic.id':'DiagnosticDeviceHasBeenUnpluggedId',驱动程序:'UnknownDriverId',版本:'00000000000061b9',id:'a30M9pPNZSEq7DgUdYrF8xw'}
  • 我应该补充一点,它在浏览器中正确显示,没有引号,但是当在带有节点的 shell 中运行时,.id 列添加了引号。
【解决方案2】:

你可以使用foreach,然后使用Object.keys你可以重命名键:

data.forEach((o, i) => {
    Object.keys(o).forEach((k) => {
        o[`0.${i}.${k}`] = o[k];
        delete o[k];
    });
});

一个例子:

let data = [
    {
      activeFrom: '2018-02-15T16:02:20.003Z',
      activeTo: '2018-02-15T16:02:20.003Z',
      distance: 0,
      duration: '00:00:00',
      rule: [Object],
      device: [Object],
      diagnostic: [Object],
      driver: 'UnknownDriverId',
      version: '00000000000061b9',
      id: 'a30M9pPNZSEq7DgUdYrF8xw'
    },
    {
      activeFrom: '2018-02-15T16:06:03.003Z',
      activeTo: '2018-02-15T16:06:03.003Z',
      distance: 0,
      duration: '00:00:00',
      rule: [Object],
      device: [Object],
      diagnostic: [Object],
      driver: 'UnknownDriverId',
      version: '00000000000061bb',
      id: 'apk5czda9o06cwRzkSl4_dQ'
    }
  ];

data.forEach((o, i) => {
    Object.keys(o).forEach((k) => {
        o[`0.${i}.${k}`] = o[k];
        delete o[k];
    });
});
console.log(data);

更新:

你可以使用map函数来达到你想要的效果:

const result = data.map(({ rule, device, diagnostic, ...rest})=>(
    { 'rule.id': 'RuleUnauthorizedDeviceRemovalId', 
      'device.id': 'b1', 'diagnostic.id': 
      'DiagnosticDeviceHasBeenUnpluggedId', ...rest }));

一个例子:

let data = [
    {
      activeFrom: '2018-02-15T16:02:20.003Z',
      activeTo: '2018-02-15T16:02:20.003Z',
      distance: 0,
      duration: '00:00:00',
      rule: [Object],
      device: [Object],
      diagnostic: [Object],
      driver: 'UnknownDriverId',
      version: '00000000000061b9',
      id: 'a30M9pPNZSEq7DgUdYrF8xw'
    },
    {
      activeFrom: '2018-02-15T16:06:03.003Z',
      activeTo: '2018-02-15T16:06:03.003Z',
      distance: 0,
      duration: '00:00:00',
      rule: [Object],
      device: [Object],
      diagnostic: [Object],
      driver: 'UnknownDriverId',
      version: '00000000000061bb',
      id: 'apk5czda9o06cwRzkSl4_dQ'
    }
  ];

const result = data.map(({ rule, device, diagnostic, ...rest})=>({ 'rule.id': 'RuleUnauthorizedDeviceRemovalId'
    , 'device.id': 'b1', 'diagnostic.id': 'DiagnosticDeviceHasBeenUnpluggedId', ...rest }));
console.log(result);

【讨论】:

  • 我正在尝试删除所有引导基本键的字符(activeFrom,activeTo)。不过,我很感激尝试。
  • 运行您的代码建议时,所有键都以 0.0 或 0.1 开头。我希望摆脱那些领先的数字和时期。我在我原来的问题的底部提到了这一点,但可能已经丢失了。我会编辑帖子。谢谢。此外,您的建议不会展平规则、设备和诊断密钥数组。
  • 规则、设备和诊断的值在我原始帖子的最后一段代码中。在该示例中,它们是 'rule.id': 'RuleUnauthorizedDeviceRemovalId', 'device.id': 'b1', 'diagnostic.id': 'DiagnosticDeviceHasBeenUnpluggedId', @StepUp
猜你喜欢
  • 2021-06-09
  • 2021-10-19
  • 2012-05-29
  • 1970-01-01
  • 1970-01-01
  • 2020-03-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多