在C#中按Control_Code分组将CSV转换为多份JSON文件
解决方案:C#按Control_Code分组将CSV转换为多份JSON文件
场景与需求
我是C#和JSON新手,需处理如下格式的固定宽度CSV文件:
Time Control_Code Metric Organisation Value DateTime 2018-10-21T00:08:03 JKX 3721 AD450 20 2018-10-21T00:08:00 2018-10-21T00:08:03 BHY 1234 HG650 88 2018-10-21T00:08:00
要求:
- 按
Control_Code分组,每个分组生成独立的JSON文件 - 同
Control_Code的指标数据整合到JSON的metrics数组中 - 目标JSON格式示例(以JKX为例):
{ "time": "2018-10-21T00:08:03", "control_Code": "JKX", "metrics": [ { "metric": 3721, "organisation": "AD450", "value": 20, "datetime": "2018-10-21T00:08:00" } ] }
(注:若需保留原属性大小写,可调整JSON序列化配置)
实现步骤
1. 安装依赖NuGet包
使用CsvHelper处理固定宽度CSV(比手动解析更稳定),用.NET内置的System.Text.Json做JSON序列化:
- 打开NuGet包管理器,搜索并安装
CsvHelper
2. 定义数据模型
根据CSV结构和目标JSON结构,创建三个类:
// 映射CSV每一行的结构 public class CsvRecord { public string Time { get; set; } public string Control_Code { get; set; } public int Metric { get; set; } public string Organisation { get; set; } public int Value { get; set; } public string DateTime { get; set; } } // 最终输出的JSON根结构 public class ControlCodeJson { public string Time { get; set; } public string Control_Code { get; set; } public List<MetricItem> metrics { get; set; } = new(); } // JSON中metrics数组的子项结构 public class MetricItem { public int Metric { get; set; } public string Organisation { get; set; } public int Value { get; set; } // 若需严格匹配示例中的"Datetime"大小写,添加此特性 [JsonPropertyName("Datetime")] public string DateTime { get; set; } }
3. 配置CSV映射(处理固定宽度)
创建映射类,指定CSV列的索引(适配固定宽度格式):
using CsvHelper.Configuration; public class CsvRecordMap : ClassMap<CsvRecord> { public CsvRecordMap() { Map(m => m.Time).Index(0); Map(m => m.Control_Code).Index(1); Map(m => m.Metric).Index(2); Map(m => m.Organisation).Index(3); Map(m => m.Value).Index(4); Map(m => m.DateTime).Index(5); } }
4. 读取CSV、分组并生成JSON
完整代码示例:
using System.Globalization; using System.Text.Json; using CsvHelper; using System.IO; class Program { static void Main(string[] args) { // 替换为你的CSV文件路径 string csvPath = @"C:\your-path\data.csv"; List<CsvRecord> csvRecords; // 读取CSV文件 using (var reader = new StreamReader(csvPath)) using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) { csv.Context.RegisterClassMap<CsvRecordMap>(); // 跳过空行(如果CSV有多余空行) csv.Context.Configuration.IgnoreBlankLines = true; csvRecords = csv.GetRecords<CsvRecord>().ToList(); } // 按Control_Code分组 var groupedData = csvRecords.GroupBy(record => record.Control_Code); // JSON序列化配置:格式化输出,可选camelCase var jsonOptions = new JsonSerializerOptions { WriteIndented = true, // 若不需要camelCase,注释掉下面一行 PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; // 遍历分组生成JSON文件 foreach (var group in groupedData) { string controlCode = group.Key; var jsonModel = new ControlCodeJson { Time = group.First().Time, Control_Code = controlCode, metrics = group.Select(record => new MetricItem { Metric = record.Metric, Organisation = record.Organisation, Value = record.Value, DateTime = record.DateTime }).ToList() }; // 序列化并写入文件,文件名用Control_Code命名 string jsonString = JsonSerializer.Serialize(jsonModel, jsonOptions); string outputPath = $"{controlCode}.json"; File.WriteAllText(outputPath, jsonString); } } }
关键注意点
- 如果同
Control_Code的Time字段不一致,需额外处理(比如取第一条、合并提示或报错),上述代码默认取分组内第一条记录的Time - 若CSV是逗号分隔而非固定宽度,只需修改
CsvRecordMap为按列名映射,无需指定索引 - 若使用Newtonsoft.Json替代
System.Text.Json,只需替换序列化代码,并将JsonPropertyName改为JsonProperty
内容的提问来源于stack exchange,提问作者Beanymattd
相关产品推荐
相关产品推荐

