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

使用Newtonsoft JSON的TypeNameHandling反序列化返回默认值问题

问题根源
  1. 私有setter属性无法被Json.NET赋值:Subscription类的所有属性都是private set,默认情况下Json.NET没有权限修改这些属性,反序列化后自然会得到默认值。
  2. 只读集合无法填充私有字段:Alerts是只读属性,每次返回的都是_alerts的新列表,Json.NET无法直接将JSON中的数据写入私有字段_alerts。
  3. DateOnly类型可能缺少序列化支持:如果使用的Json.NET版本较旧,可能没有内置的DateOnly转换器,导致日期值反序列化失败。
解决办法

办法1:给私有成员添加[JsonProperty]标记

修改Subscription类,让Json.NET能够访问私有属性和字段:

public class Subscription : AggregateRoot
{
    [JsonProperty("Alerts")] // 让Json.NET直接操作这个私有字段
    private readonly List<Alert> _alerts = new();

    [JsonProperty] // 标记后Json.NET可设置private setter的属性
    public Guid UserId { get; private set; }
    [JsonProperty]
    public SubscriptionTier subscriptionTier { get; private set; }
    [JsonProperty]
    public SubscriptionPlan subscriptionPlan { get; private set; }
    [JsonProperty]
    public DateOnly StartDate { get; private set; }
    [JsonProperty]
    public DateOnly EndDate { get; private set; }
    [JsonProperty]
    public bool IsVaild { get; private set; }
    [JsonProperty]
    public decimal ComulativeTradingVolume24H { get; private set; }
    [JsonProperty] // 假设AggregateRoot的Id属性也是private set
    public Guid Id { get; private set; }

    public IReadOnlyList<Alert> Alerts => _alerts.AsReadOnly(); // 用AsReadOnly避免重复创建列表
}

办法2:使用带[JsonConstructor]的私有构造函数

通过构造函数传参初始化对象,无需修改属性的访问权限:

public class Subscription : AggregateRoot
{
    private readonly List<Alert> _alerts = new();

    public Guid UserId { get; private set; }
    public SubscriptionTier subscriptionTier { get; private set; }
    public SubscriptionPlan subscriptionPlan { get; private set; }
    public DateOnly StartDate { get; private set; }
    public DateOnly EndDate { get; private set; }
    public bool IsVaild { get; private set; }
    public decimal ComulativeTradingVolume24H { get; private set; }
    public Guid Id { get; private set; }

    public IReadOnlyList<Alert> Alerts => _alerts.AsReadOnly();

    // 私有构造函数,添加[JsonConstructor]让Json.NET用它初始化对象
    [JsonConstructor]
    private Subscription(
        Guid userId,
        SubscriptionTier subscriptionTier,
        SubscriptionPlan subscriptionPlan,
        DateOnly startDate,
        DateOnly endDate,
        bool isVaild,
        decimal comulativeTradingVolume24H,
        List<Alert> alerts,
        Guid id)
    {
        UserId = userId;
        this.subscriptionTier = subscriptionTier;
        this.subscriptionPlan = subscriptionPlan;
        StartDate = startDate;
        EndDate = endDate;
        IsVaild = isVaild;
        ComulativeTradingVolume24H = comulativeTradingVolume24H;
        _alerts = alerts ?? new List<Alert>();
        Id = id;
    }

    // 保留业务逻辑需要的公共构造函数
    public Subscription(Guid userId, SubscriptionTier tier, SubscriptionPlan plan, DateOnly startDate, DateOnly endDate)
    {
        UserId = userId;
        subscriptionTier = tier;
        subscriptionPlan = plan;
        StartDate = startDate;
        EndDate = endDate;
        IsVaild = true;
        ComulativeTradingVolume24H = 0;
        Id = Guid.NewGuid();
    }
}

办法3:添加DateOnly自定义转换器(若需要)

如果你的Json.NET版本不支持DateOnly,自定义转换器并添加到序列化设置中:

public class DateOnlyConverter : JsonConverter<DateOnly>
{
    private const string DateFormat = "yyyy-MM-dd";

    public override DateOnly ReadJson(JsonReader reader, Type objectType, DateOnly existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        return DateOnly.ParseExact(reader.Value.ToString(), DateFormat, CultureInfo.InvariantCulture);
    }

    public override void WriteJson(JsonWriter writer, DateOnly value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString(DateFormat, CultureInfo.InvariantCulture));
    }
}

更新序列化和反序列化代码:

// 序列化
JsonConvert.SerializeObject(domainEvent, 
    new JsonSerializerSettings 
    { 
        TypeNameHandling = TypeNameHandling.All,
        Converters = { new DateOnlyConverter() }
    });

// 反序列化
var domainEvent = JsonConvert.DeserializeObject<IDomainEvent>(
    serializedDomainEvent,
    new JsonSerializerSettings 
    { 
        TypeNameHandling = TypeNameHandling.All,
        Converters = { new DateOnlyConverter() }
    });
验证修改

完成修改后重新执行序列化和反序列化流程,检查Subscription对象的属性值是否正常填充,而非默认的空Guid、0等值。

内容的提问来源于stack exchange,提问作者Sulabee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 19:04:54