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

如何映射含数据数组与日期的JSON数据以适配D3.js多线图?

嘿,我完全懂你现在的困扰——把这种嵌套结构的JSON转换成D3多线图需要的扁平键值对格式,确实得绕个弯子。我来一步步帮你把这个问题解决掉!

首先,先明确咱们的原始数据结构和目标格式:

你的原始JSON结构

假设你的数据长这样(我补了点示例值方便理解):

{
  "Session_test": [
    {
      "datas_lines": [
        {
          "log_time": "2024-01-01",
          "datas_line": [12, 28, 45]
        },
        {
          "log_time": "2024-01-02",
          "datas_line": [18, 32, 50]
        },
        {
          "log_time": "2024-01-03",
          "datas_line": [22, 35, 58]
        }
      ]
    }
  ]
}

咱们需要的目标格式

要把它转成每个日期对应多条线数值的结构,像这样:

[
  { "log_time": "2024-01-01", "line0": 12, "line1": 28, "line2": 45 },
  { "log_time": "2024-01-02", "line0": 18, "line1": 32, "line2": 50 },
  { "log_time": "2024-01-03", "line0": 22, "line1": 35, "line2": 58 }
]

第一步:数据格式转换

用几行JavaScript就能完成这个转换,核心是遍历原始数据,把datas_line里的每个数值按索引转成单独的键:

// 先从原始JSON里取出核心的datas_lines数组
const rawLines = yourJsonData.Session_test[0].datas_lines;

// 转换格式
const transformedData = rawLines.map(item => {
  // 先初始化包含日期的对象
  const formattedItem = { log_time: item.log_time };
  // 遍历datas_line数组,给每个数值生成对应的键(line0、line1...)
  item.datas_line.forEach((value, index) => {
    formattedItem[`line${index}`] = value;
  });
  return formattedItem;
});

这段代码的逻辑很简单:先把每个log_time拿出来,再把datas_line里的每个值按顺序命名成line0、line1这样的属性,最后拼成我们需要的扁平对象。


第二步:适配D3多线图代码

现在你就可以复用那个帖子里的代码了,只需要做一点小调整来处理转换后的数据:

1. 解析日期(必不可少!)

D3的时间比例尺需要日期对象,所以先把字符串转成日期:

const parseTime = d3.timeParse('%Y-%m-%d');
transformedData.forEach(d => {
  d.log_time = parseTime(d.log_time);
});

2. 准备每条线的数据集

我们需要把转换后的数据拆分成每条线单独的数组:

// 提取所有线条的名称(排除log_time)
const lineKeys = Object.keys(transformedData[0]).filter(key => key !== 'log_time');

// 为每条线生成对应的数据集
const lineDatasets = lineKeys.map(key => {
  return transformedData.map(d => {
    return { date: d.log_time, value: d[key] };
  });
});

3. 绘制线条

接下来就可以用D3的线条生成器来绘制了,和那个帖子里的逻辑一致:

// 假设你已经定义好了x、y比例尺和颜色比例尺
const lineGenerator = d3.line()
  .x(d => xScale(d.date))
  .y(d => yScale(d.value))
  .curve(d3.curveMonotoneX); // 可选:让线条更平滑

// 绘制所有线条
svg.selectAll('.multi-line')
  .data(lineDatasets)
  .enter()
  .append('path')
  .attr('class', 'multi-line')
  .attr('d', lineGenerator)
  .style('stroke', (d, i) => colorScale(i))
  .style('fill', 'none')
  .style('stroke-width', 2);

额外注意事项

  • 如果你的datas_line数组长度在不同日期里不一致,记得加个边界判断,避免出现undefined的情况;
  • 如果需要自定义线条名称(不想用line0、line1),可以在原始JSON里加个line_names数组,转换的时候用这个数组里的名称代替索引;
  • 别忘了给图表加坐标轴、图例这些元素,让它更完整!

内容的提问来源于stack exchange,提问作者Patrick Michel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:04:13