C#反序列化嵌套JSON 合并多模型数据至单个CollectionView
问题根因
- 一是实体类定义存在错误:
Queryresult类中嵌套的客户属性定义成了Customer1类型,和实际嵌套的Customer2结构不匹配,反序列化时这层数据无法被正确填充 - 二是反序列化代码存在大小写错误:C#是大小写敏感语言,定义的根类名是
Root,反序列化时写的小写root会导致编译失败 - 三是直接使用原始嵌套结构的
Customer1集合作为绑定源,没有做多层数据的扁平化处理,无法拿到深层的Customer2、Lastpayment数据
实现步骤
1. 修正实体定义
首先修正Queryresult类的属性错误,对齐接口返回结构:
public class Queryresult { public string responseMessage { get; set; } // 原代码此处错误定义为Customer1类型,修正为Customer2,属性名和接口返回字段保持一致 public Customer2 customer2 { get; set; } public int responseCode { get; set; } public string status { get; set; } }
如果接口返回的字段名和C#属性名不一致,可以用JsonProperty特性做映射,避免反序列化失败。
2. 定义统一绑定用的扁平化模型
创建专门用于UI绑定的模型类,把三个层级需要展示的字段全部平铺定义,不需要保留嵌套结构:
public class CustomerDisplayItem { // Customer1 层级字段 public string district { get; set; } public string feeder { get; set; } public string feeder_code { get; set; } public string transformer { get; set; } public string dss_code { get; set; } public string database_match { get; set; } public string accountnumber { get; set; } public string meterno { get; set; } // Customer2 层级字段 public string phoneNumber { get; set; } public int billedAmount { get; set; } public object billedDate { get; set; } public string lastPayDate { get; set; } // Lastpayment 层级字段 public string transactionRef { get; set; } public int units { get; set; } public string transactionDate { get; set; } public string transactionId { get; set; } public int transactionBookId { get; set; } public int amountPaid { get; set; } public int mscPaid { get; set; } public string invoiceNumber { get; set; } }
3. 反序列化后投影展平数据
修正反序列化的类型名错误,通过LINQ访问各层嵌套数据,映射为统一的扁平化集合,过程中做空值容错避免空引用异常:
// 修正类名大小写错误,使用正确的Root类型反序列化 var data = JsonConvert.DeserializeObject<Root>(readTask); if (data?.result?.Customer1 == null) { // 处理接口返回空数据场景,绑定空集合即可 yourCollectionView.ItemsSource = new ObservableCollection<CustomerDisplayItem>(); return; } // 逐层访问嵌套数据,映射为统一的展示模型集合 var bindableCollection = new ObservableCollection<CustomerDisplayItem>( data.result.Customer1.Select(c1 => { // 空值容错获取Customer2层数据 Customer2 c2 = c1.transactional_details?.queryresult?.customer2; // 空值容错获取Lastpayment层数据 Lastpayment lastPay = c2?.lastpayment; return new CustomerDisplayItem { // 映射Customer1字段 district = c1.district, feeder = c1.feeder, feeder_code = c1.feeder_code, transformer = c1.transformer, dss_code = c1.dss_code, database_match = c1.database_match, accountnumber = c1.accountnumber, meterno = c1.meterno, // 映射Customer2字段,空值赋默认值 phoneNumber = c2?.phoneNumber, billedAmount = c2?.billedAmount ?? 0, billedDate = c2?.billedDate, lastPayDate = c2?.lastPayDate, // 映射Lastpayment字段,空值赋默认值 transactionRef = lastPay?.transactionRef, units = lastPay?.units ?? 0, transactionDate = lastPay?.transactionDate, transactionId = lastPay?.transactionId, transactionBookId = lastPay?.transactionBookId ?? 0, amountPaid = lastPay?.amountPaid ?? 0, mscPaid = lastPay?.mscPaid ?? 0, invoiceNumber = lastPay?.invoiceNumber }; }) ); // 将最终展平的集合绑定到CollectionView yourCollectionView.ItemsSource = bindableCollection;
注意事项
- 所有嵌套层级访问都使用了null条件运算符
?.,避免某一层数据缺失时抛出空引用异常 - 值类型字段(比如int类型的金额、数量)空值时用
??运算符赋值默认值0,避免绑定时报错 - 如果后续需要修改集合,直接操作
bindableCollection即可,它是ObservableCollection类型,会自动通知UI更新
内容的提问来源于stack exchange,提问作者GIS Support EEDC
相关产品推荐
相关产品推荐

