将CSV导入Pandas并按列值生成层级JSON结构的技术问询
用C# CSVHelper + AutoMapper实现CSV分组转层级JSON
步骤1:定义实体类
先对应CSV行和最终输出结构定义强类型类,方便后续处理:
// 对应CSV每行数据的实体 public class CsvLocationRecord { public int personal_id { get; set; } public string location_type { get; set; } public int location_number { get; set; } } // 最终输出的层级结构实体 public class PersonalLocationResult { public int personal_id { get; set; } public List<int>? company { get; set; } public List<int>? branch { get; set; } }
步骤2:用CSVHelper流式读取CSV
针对数十万行的大文件,必须用流式读取避免内存溢出,同时处理CSV中location_type带单引号的格式:
using var reader = new StreamReader("你的CSV文件路径.csv"); using var csv = new CsvReader(reader, CultureInfo.InvariantCulture); // 配置读取规则:忽略大小写匹配表头,解析带单引号的字符串 csv.Configuration.PrepareHeaderForMatch = header => header.ToLower(); csv.Configuration.TypeConverterOptionsCache.GetOptions<string>().Formats = new[] { "'{0}'" }; // 流式读取所有行(延迟加载,不会一次性加载到内存) var records = csv.GetRecords<CsvLocationRecord>();
步骤3:LINQ分组+数据整理
直接用LINQ按personal_id分组,将不同location_type对应的location_number归类到对应列表:
var groupedData = records .GroupBy(r => r.personal_id) .Select(g => new PersonalLocationResult { personal_id = g.Key, company = g.Where(r => r.location_type.Equals("company", StringComparison.OrdinalIgnoreCase)) .Select(r => r.location_number) .ToList(), branch = g.Where(r => r.location_type.Equals("branch", StringComparison.OrdinalIgnoreCase)) .Select(r => r.location_number) .ToList() }) // 过滤空列表,和示例输出格式对齐 .Select(result => { if (!result.company?.Any() ?? true) result.company = null; if (!result.branch?.Any() ?? true) result.branch = null; return result; }) .ToList();
步骤4:用AutoMapper简化映射(可选)
如果想用AutoMapper替代手动映射,先创建映射配置再转换:
var config = new MapperConfiguration(cfg => { cfg.CreateMap<IGrouping<int, CsvLocationRecord>, PersonalLocationResult>() .ForMember(dest => dest.personal_id, opt => opt.MapFrom(src => src.Key)) .ForMember(dest => dest.company, opt => opt.MapFrom(src => src.Where(r => r.location_type == "company").Select(r => r.location_number))) .ForMember(dest => dest.branch, opt => opt.MapFrom(src => src.Where(r => r.location_type == "branch").Select(r => r.location_number))); }); var mapper = config.CreateMapper(); // 用AutoMapper转换分组数据 var groupedData = records .GroupBy(r => r.personal_id) .Select(mapper.Map<PersonalLocationResult>) .Select(result => { if (!result.company?.Any() ?? true) result.company = null; if (!result.branch?.Any() ?? true) result.branch = null; return result; }) .ToList();
步骤5:序列化为目标格式JSON
用System.Text.Json或Newtonsoft.Json生成符合要求的JSON:
// 使用System.Text.Json var json = JsonSerializer.Serialize(groupedData, new JsonSerializerOptions { WriteIndented = true, // 格式化输出 IgnoreNullValues = true // 忽略空属性,和示例对齐 }); // 或者使用Newtonsoft.Json // var json = JsonConvert.SerializeObject(groupedData, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); // 将JSON写入文件 File.WriteAllText("输出文件路径.json", json);
关键注意事项
- 大文件适配:流式读取+LINQ延迟执行确保不会一次性加载数十万行数据到内存,避免内存溢出
- 格式兼容:通过CSVHelper配置自动解析带单引号的
location_type值 - 输出对齐:通过忽略空属性,让最终JSON和示例格式完全一致
内容的提问来源于stack exchange,提问作者TGR
相关产品推荐
相关产品推荐

