You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:18:13