如何用TypeScript/JavaScript将扁平JSON转为问卷层级结构?可借助Lodash吗?
如何用Lodash将扁平JSON转换为问卷层级结构?
我有一份扁平JSON数据,需要使用TypeScript/JavaScript将其转换为层级结构,用于后续构建问卷。想知道是否可以用Lodash或类似库实现这个转换?
TypeScript类定义
export class Template { template_id: number; template_name: string; sections: Section[]; } export class Section { section_id: number; section_name: string; fields: Field[]; } export class Field { field_id: number; field_lable : string; input_type: InputType; } export class InputType { input_type_id: number; input_type_name: string; }
扁平数据示例(最终需转换为Template数组)
[ { "Template_id":1, "Template_Name":"Enterprise", "Section_id":1, "Section_Name":"Basic Info", "Field_id":1, "Field_Label":"Enter Your Name", "Input_Type_id":1, "Input_Type_Name":"Text" }, { "Template_id":1, "Template_Name":"Enterprise", "Section_id":1, "Section_Name":"Basic Info", "Field_id":2, "Field_Label":"Enter Your Address", "Input_Type_id":1, "Input_Type_Name":"Text" }, { "Template_id":1, "Template_Name":"Enterprise", "Section_id":2, "Section_Name":"Environment", "Field_id":3, "Field_Label":"Do you believe in environment", "Input_Type_id":3, "Input_Type_Name":"Checkbox" }, { "Template_id":1, "Template_Name":"Enterprise", "Section_id":3, "Section_Name":"Transfer", "Field_id":4, "Field_Label":"Select prefer transfer modes", "Input_Type_id":2, "Input_Type_Name":"Dropdown" }, { "Template_id":2, "Template_Name":"RRR", "Section_id":4, "Section_Name":"Basic Info", "Field_id":5, "Field_Label":"Enter Your Name", "Input_Type_id":1, "Input_Type_Name":"Text" }, { "Template_id":2, "Template_Name":"RRR", "Section_id":4, "Section_Name":"Basic Info", "Field_id":6, "Field_Label":"Enter Your Address", "Input_Type_id":1, "Input_Type_Name":"Text" }, { "Template_id":2, "Template_Name":"RRR", "Section_id":5, "Section_Name":"GPO", "Field_id":7, "Field_Label":"Select names of GPOs", "Input_Type_id":2, "Input_Type_Name":"Dropdown" }, { "Template_id":2, "Template_Name":"RRR", "Section_id":6, "Section_Name":"Unit", "Field_id":8, "Field_Label":"Enter name of your unit", "Input_Type_id":1, "Input_Type_Name":"Text" } ]
期望输出
[ { "Template_id":1, "Template_Name":"Enterprise", "Sections":[ { "Section_id":1, "Section_Name":"Basic Info", "Fields":[ { "Field_id":1, "Field_Label":"Enter Your Name", "Input_Type_id":1, "Input_Type_Name":"Text" }, { "Field_id":2, "Field_Label":"Enter Your Address", "Input_Type_id":1, "Input_Type_Name":"Text" } ] }, { "Section_id":2, "Section_Name":"Environment", "Fields":[ { "Field_id":3, "Field_Label":"Do you believe in environment", "Input_Type_id":3, "Input_Type_Name":"Checkbox" } ] } ] }, { "Template_id":2, "Template_Name":"RRR", "Sections":[ { "Section_id":4, "Section_Name":"Basic Info", "Fields":[ { "Field_id":5, "Field_Label":"Enter Your Name", "Input_Type_id":1, "Input_Type_Name":"Text" }, { "Field_id":6, "Field_Label":"Enter Your Address", "Input_Type_id":1, "Input_Type_Name":"Text" } ] }, { "Section_id":5, "Section_Name":"GPO", "Fields":[ { "Field_id":7, "Field_Label":"Select names of GPOs", "Input_Type_id":2, "Input_Type_Name":"Dropdown" } ] } ] } ]
解决方案
用Lodash实现
Lodash的groupBy方法可以快速完成分组,再逐层组装层级结构:
import _ from 'lodash'; // 定义扁平数据的类型 interface FlatDataItem { Template_id: number; Template_Name: string; Section_id: number; Section_Name: string; Field_id: number; Field_Label: string; Input_Type_id: number; Input_Type_Name: string; } // 定义输出结构的类型 interface TemplateOutput { Template_id: number; Template_Name: string; Sections: { Section_id: number; Section_Name: string; Fields: Omit<FlatDataItem, 'Template_id' | 'Template_Name' | 'Section_id' | 'Section_Name'>[]; }[]; } function transformFlatData(flatData: FlatDataItem[]): TemplateOutput[] { // 第一步:按Template_id分组 const groupedByTemplate = _.groupBy(flatData, 'Template_id'); return Object.values(groupedByTemplate).map(templateItems => { // 提取模板的基础信息 const { Template_id, Template_Name } = templateItems[0]; // 第二步:在当前模板组内按Section_id分组 const groupedBySection = _.groupBy(templateItems, 'Section_id'); // 组装章节数组 const sections = Object.values(groupedBySection).map(sectionItems => { const { Section_id, Section_Name } = sectionItems[0]; // 提取字段信息,去除冗余字段 const fields = sectionItems.map(item => ({ Field_id: item.Field_id, Field_Label: item.Field_Label, Input_Type_id: item.Input_Type_id, Input_Type_Name: item.Input_Type_Name })); return { Section_id, Section_Name, Fields: fields }; }); return { Template_id, Template_Name, Sections: sections }; }); }
原生JavaScript实现(无需Lodash)
如果不想引入第三方库,用原生reduce方法也能实现相同逻辑:
function transformFlatDataNative(flatData: FlatDataItem[]): TemplateOutput[] { return flatData.reduce((templates, item) => { // 查找或创建当前模板 let template = templates.find(t => t.Template_id === item.Template_id); if (!template) { template = { Template_id: item.Template_id, Template_Name: item.Template_Name, Sections: [] }; templates.push(template); } // 查找或创建当前章节 let section = template.Sections.find(s => s.Section_id === item.Section_id); if (!section) { section = { Section_id: item.Section_id, Section_Name: item.Section_Name, Fields: [] }; template.Sections.push(section); } // 添加字段到章节 section.Fields.push({ Field_id: item.Field_id, Field_Label: item.Field_Label, Input_Type_id: item.Input_Type_id, Input_Type_Name: item.Input_Type_Name }); return templates; }, [] as TemplateOutput[]); }
内容的提问来源于stack exchange,提问作者Visha
相关产品推荐
相关产品推荐

