如何用C#扁平化拆分包含多订单项的订单列表?
解决方案
核心思路
通过DTO类适配原始JSON字段,结合LINQ的SelectMany方法实现订单的扁平化拆分,同时处理JSON中字段名不一致的情况,代码简洁且逻辑清晰。
步骤实现
1. 定义适配JSON的DTO类
由于原始JSON的字段名与目标Order/OrderItem类不匹配,先定义中间DTO类来接收反序列化的数据:
using System.Text.Json.Serialization; public class RawOrderDto { [JsonPropertyName("order_id")] public int OrderID { get; set; } [JsonPropertyName("total_price")] public int TotalPrice { get; set; } [JsonPropertyName("items")] public List<RawOrderItemDto>? Items { get; set; } [JsonPropertyName("products_info")] public List<RawOrderItemDto>? ProductsInfo { get; set; } } public class RawOrderItemDto { [JsonPropertyName("name")] public string? Name { get; set; } [JsonPropertyName("product_name")] public string? ProductName { get; set; } [JsonPropertyName("price")] public int Price { get; set; } [JsonPropertyName("product_price")] public int ProductPrice { get; set; } [JsonPropertyName("sku")] public string? SKU { get; set; } }
2. 反序列化+拆分订单的核心逻辑
利用LINQ的SelectMany将每个原始订单拆分为多个单个订单项的订单,同时完成字段映射:
using System.Text.Json; using System.Linq; // 原始JSON字符串 var rawJson = @"[ { ""order_id"": 1, ""total_price"": 700, ""items"": [ { ""name"": ""cellphone"", ""price"": 500, ""sku"": ""1s4f"" }, { ""product_name"": ""airphones"", ""product_price"": 200, ""sku"": ""1ar4"" } ] }, { ""order_id"": 2, ""total_price"": 5000, ""products_info"": [ { ""name"": ""car"", ""price"": 2500, ""sku"": ""8y5t"" }, { ""name"": ""battery"", ""price"": 1500, ""sku"": ""5g3g"" }, { ""name"": ""insurance"", ""price"": 1000, ""sku"": ""5r8f"" } ] } ]"; // 反序列化到DTO列表 var rawOrders = JsonSerializer.Deserialize<List<RawOrderDto>>(rawJson) ?? []; // 拆分并转换为目标Order类型 var splitOrders = rawOrders .SelectMany(rawOrder => { // 兼容两种订单项字段名 var items = rawOrder.Items ?? rawOrder.ProductsInfo ?? []; return items.Select((item, index) => new Order { // 用原ID+序号生成新订单ID,保持关联 OrderID = int.Parse($"{rawOrder.OrderID}-{index + 1}"), // 单个订单项价格作为新订单总价 TotalPrice = item.Price != 0 ? item.Price : item.ProductPrice, Items = new List<OrderItem> { new OrderItem { Name = item.Name ?? item.ProductName, Price = item.Price != 0 ? item.Price : item.ProductPrice, SKU = item.SKU } } }); }) .ToList(); // 验证输出 foreach (var order in splitOrders) { Console.WriteLine($"订单ID: {order.OrderID}, 总价: {order.TotalPrice}"); Console.WriteLine($"商品: {order.Items[0].Name}, 价格: {order.Items[0].Price}, SKU: {order.Items[0].SKU}"); Console.WriteLine("---"); }
方案优势
- 可读性高:LINQ链式调用清晰表达"拆分每个订单为单个订单项订单"的逻辑。
- 兼容性强:处理了JSON中字段名不一致的情况(如
items/products_info、name/product_name)。 - 低侵入性:无需修改原有
Order/OrderItem类,通过DTO做中间适配。
内容的提问来源于stack exchange,提问作者FMgr
相关产品推荐
相关产品推荐

