C#如何反序列化ICollection类型JSON属性中的子项类型?
问题:遍历反序列化后的集合时如何获取项的实际类型?
我有如下格式的包含集合的JSON数据:
{ "Store": 12, "TransactionItems": { "$type": "System.Collections.ObjectModel.Collection`1[[BaseTransactionItem, Common]], mscorlib", "$values": [ { "$type": "TransactionSaleItem, Common", "Description": "Grey Shirt", "ActualSalePrice": 40.0, "ActualSalePricePerItem": 40.0 }, { "$type": "TransactionReturnItem, Common", "Description": "Red Shirt", "ActualSalePrice": -30.0, "ActualSalePricePerItem": -30.0 } ] }, "CountryCode": "GB" }
使用Newtonsoft NuGet包反序列化后,我能访问到TransactionItems集合,其中的两个项均为BaseTransactionItem类型。请问遍历这些项时,如何获取每个项的实际类型(即TransactionSaleItem和TransactionReturnItem)?
简化后的C#代码如下:
[DataContract(IsReference = true)] public class Transaction : IEquatable<Transaction> { [DataMember] public int Store { get; set; } [DataMember] public ICollection<BaseTransactionItem> TransactionItems { get; set; } [DataMember] public string CountryCode { get; set; } } [DataContract] [KnownType(typeof(TransactionOrderItem))] [KnownType(typeof(TransactionReturnItem))] [KnownType(typeof(TransactionSaleItem))] public class BaseTransactionItem : IEquatable<BaseTransactionItem> { } [DataContract] public class TransactionReturnItem : BaseTransactionItem, IEquatable<TransactionReturnItem> { } [DataContract] public class TransactionSaleItem : BaseTransactionItem, IEquatable<TransactionSaleItem> { }
解决方案
1. 直接使用GetType()获取运行时类型
对集合中的每个BaseTransactionItem实例调用GetType()方法,就能得到它的实际运行时类型:
foreach (var item in transaction.TransactionItems) { Type actualType = item.GetType(); Console.WriteLine($"当前项的实际类型:{actualType.Name}"); }
执行后会输出TransactionSaleItem和TransactionReturnItem,直接拿到具体的类型对象,方便后续的类型判断或反射操作。
2. 用is/as运算符做类型检查与转换
如果需要针对不同类型执行差异化逻辑,推荐用is关键字直接判断并转换,代码更简洁:
foreach (var item in transaction.TransactionItems) { if (item is TransactionSaleItem saleItem) { // 处理销售商品的逻辑,比如读取Description Console.WriteLine($"销售商品:{saleItem.Description}"); } else if (item is TransactionReturnItem returnItem) { // 处理退货商品的逻辑 Console.WriteLine($"退货商品:{returnItem.Description}"); } }
这种方式既完成了类型判断,又直接得到了强类型的对象,无需额外强制转换。
3. (可选)读取JSON中的$type字段
如果需要直接获取JSON里的类型标识字符串,可以将对象转为JObject后读取,但这种方式一般没必要,因为GetType()已经能提供更实用的Type对象:
using Newtonsoft.Json.Linq; foreach (var item in transaction.TransactionItems) { JObject jObj = JObject.FromObject(item); string typeString = jObj["$type"]?.ToString(); Console.WriteLine($"JSON中的类型标识:{typeString}"); }
内容的提问来源于stack exchange,提问作者Bhav
相关产品推荐
相关产品推荐

