带嵌套列表属性的类转CSV格式异常,求正确序列化方案
解决ServiceStack.Text CSV序列化嵌套列表的扁平化问题
你遇到的问题是因为ServiceStack.Text的默认CSV序列化不会自动展开嵌套的集合类型,所以会把List<TDeal>和List<TInterval>序列化为它们的字符串表示(也就是你看到的[{ }]格式)。要得到你期望的扁平化CSV格式,我们需要先把嵌套的数据结构转换成适合CSV的扁平DTO,再进行序列化。
下面是具体的实现步骤:
1. 定义扁平的CSV记录类
首先创建一个和你期望的CSV列对应的DTO类,用来存储每条扁平化的记录:
public class FlatDealRecord { public string Client { get; set; } public string DealNo { get; set; } // 对应原TDeal的DealName public string StartDate { get; set; } public string EndDate { get; set; } public string Volume { get; set; } }
2. 编写转换方法,将嵌套结构转为扁平列表
接下来写一个方法,把你的TRoot对象转换成List<FlatDealRecord>,处理两种情况:
- 没有
TShape的Deal,用-填充时间和Volume字段 - 有
TShape的Deal,每个Interval对应一行记录
public static List<FlatDealRecord> ConvertRootToFlatRecords(TRoot root) { var flatRecords = new List<FlatDealRecord>(); // 空值判断,避免空引用异常 if (root == null || root.Deals == null) return flatRecords; foreach (var deal in root.Deals) { // 处理没有Interval的Deal if (deal.TShape == null || !deal.TShape.Any()) { flatRecords.Add(new FlatDealRecord { Client = root.Client, DealNo = deal.DealName, StartDate = "-", EndDate = "-", Volume = "-" }); continue; } // 遍历每个Interval,生成对应的扁平记录 foreach (var interval in deal.TShape) { flatRecords.Add(new FlatDealRecord { Client = root.Client, DealNo = deal.DealName, StartDate = interval.StartDate ?? "-", EndDate = interval.EndDate ?? "-", Volume = interval.Volume ?? "-" }); } } return flatRecords; }
3. 序列化扁平列表到CSV
最后用ServiceStack.Text序列化这个扁平列表,就能得到你想要的格式了:
// 假设你已经有了TRoot的实例 var yourRootData = new TRoot { Client = "ABC", Deals = new List<TDeal> { new TDeal { DealName = "59045599", TShape = new List<TInterval> { new TInterval { StartDate = "2014-01-28T23:00:00", EndDate = "2014-01-28T23:30:00", Volume = "0.00" }, new TInterval { StartDate = "2014-01-28T23:30:00", EndDate = "2014-01-29T00:00:00", Volume = "0.00" } } } } }; // 转换为扁平记录 var flatRecords = ConvertRootToFlatRecords(yourRootData); // 写入CSV文件 using (var writer = new StreamWriter("output.csv")) { CsvSerializer.SerializeToWriter(flatRecords, writer); }
为什么默认序列化不行?
CSV是一种二维表格格式,本身不支持嵌套的层级结构。ServiceStack.Text的默认CSV序列化对于集合类型,只会输出它们的ToString()结果(也就是你看到的[{DealName:...}]这种格式),所以必须手动把嵌套的数据展开成一维的记录列表,才能符合CSV的结构要求。
这种手动转换的方式也给了你最大的灵活性,比如你可以根据需求调整字段的填充规则、排序方式等。
内容的提问来源于stack exchange,提问作者mahesh
相关产品推荐
相关产品推荐

