如何将扁平CSV转换为适用于D3.js树形图的嵌套JSON?
解决CSV转D3树形图嵌套JSON的问题
嘿,我刚好处理过类似的需求,把层级CSV数据转成D3.js树形图需要的嵌套JSON格式其实不难,结合D3自带的工具就能高效搞定。先理清楚你的需求:
你的输入与预期
CSV数据示例
Domain,Subject,Section,Topic Networking,Networking Communications,Data Transmission,Data - Overview Networking,Networking Communications,Data Transmission,Email Networking,Networking Communications,Data Transmission,Datagram Networking,Networking Communications,Networking Models,OSI Model Networking,Networking Communications,Networking Models,TCP/IP Mode
预期嵌套JSON格式(适配D3树形图)
{ "name": "Networking", "groups": ["CS Analyst", "Cyber Crime"], "children": [ { "name": "Networking Communications", "groups": ["CS Analyst", "Cyber Crime"], "children": [ { "name": "Data Transmission", "groups": ["CS Analyst", "Cyber Crime"], "children": [ { "name": "Data - Overview", "groups": ["CS Analyst", "Cyber Crime"] }, { "name": "Email", "groups": ["CS Analyst", "Cyber Crime"] }, { "name": "Datagram", "groups": [] } ] }, { "name": "Networking Models", "groups": ["CS Analyst"], "children": [ { "name": "OSI Model", "groups": ["CS Analyst"] }, { "name": "TCP/IP Mode", "groups": ["CS Analyst"] } ] } ] } ] }
解决方案:JavaScript实现(基于D3.js)
我用D3自带的d3.stratify()来构建层级结构,再转换成你需要的格式,同时支持自定义每个节点的groups属性:
// 假设你已经通过d3.csv("your-data.csv")获取到了CSV数据数组 const csvData = [ { Domain: "Networking", Subject: "Networking Communications", Section: "Data Transmission", Topic: "Data - Overview" }, { Domain: "Networking", Subject: "Networking Communications", Section: "Data Transmission", Topic: "Email" }, { Domain: "Networking", Subject: "Networking Communications", Section: "Data Transmission", Topic: "Datagram" }, { Domain: "Networking", Subject: "Networking Communications", Section: "Networking Models", Topic: "OSI Model" }, { Domain: "Networking", Subject: "Networking Communications", Section: "Networking Models", Topic: "TCP/IP Mode" } ]; // 自定义每个节点的groups配置,你可以根据实际需求修改或从其他数据源导入 const groupConfig = { "Networking": ["CS Analyst", "Cyber Crime"], "Networking Communications": ["CS Analyst", "Cyber Crime"], "Data Transmission": ["CS Analyst", "Cyber Crime"], "Data - Overview": ["CS Analyst", "Cyber Crime"], "Email": ["CS Analyst", "Cyber Crime"], "Datagram": [], "Networking Models": ["CS Analyst"], "OSI Model": ["CS Analyst"], "TCP/IP Mode": ["CS Analyst"] }; // 使用d3.stratify构建层级关系 const stratify = d3.stratify() .parentId(d => { // 为每个节点指定父节点ID if (d.Topic) return `${d.Domain}/${d.Subject}/${d.Section}`; if (d.Section) return `${d.Domain}/${d.Subject}`; if (d.Subject) return d.Domain; return null; }) .id(d => { // 为每个节点生成唯一ID if (d.Topic) return `${d.Domain}/${d.Subject}/${d.Section}/${d.Topic}`; if (d.Section) return `${d.Domain}/${d.Subject}/${d.Section}`; if (d.Subject) return `${d.Domain}/${d.Subject}`; return d.Domain; }); // 生成D3层级树结构 const root = stratify(csvData); // 递归转换为你需要的JSON格式 function transformToTree(node) { const nodeName = node.id.split("/").pop(); const treeNode = { name: nodeName, groups: groupConfig[nodeName] || [] }; // 非叶子节点添加children属性 if (node.children.length > 0) { treeNode.children = node.children.map(child => transformToTree(child)); } return treeNode; } // 得到最终的树形JSON const finalTreeData = transformToTree(root); console.log(JSON.stringify(finalTreeData, null, 2));
关键说明
d3.stratify():这是D3专门处理层级数据的利器,通过定义id和parentId快速构建父子关系,比手动遍历CSV高效得多,尤其适合大数据量的情况。groupConfig:这里我手动配置了每个节点的groups,如果你的groups规则有规律(比如按层级默认值),可以改成动态生成,不用手动写每个节点的配置。- 递归转换:
transformToTree函数会递归遍历D3生成的层级节点,自动处理叶子节点(不添加children属性),完全匹配你需要的JSON结构。
这个方案直接可以集成到你的D3项目里,读取CSV后就能生成可用的树形数据啦。
内容的提问来源于stack exchange,提问作者FDRH
相关产品推荐
相关产品推荐

