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

如何阻止不可修改类型的成员被Newtonsoft.Json序列化/反序列化

解决方案

方案1:属性标注实现(完全符合需求,对现有代码侵入最小)

你可以通过自定义 JsonConverter 实现,仅需要在用到 RecurrenceInfo 的属性上加一行标注,无需修改全局序列化配置:

  1. 实现自定义转换器
public class RecurrenceInfoConverter : JsonConverter<RecurrenceInfo>
{
    public override void WriteJson(JsonWriter writer, RecurrenceInfo value, JsonSerializer serializer)
    {
        var contract = serializer.ContractResolver.ResolveContract(typeof(RecurrenceInfo)) as JsonObjectContract;
        if (contract == null)
        {
            serializer.Serialize(writer, value);
            return;
        }
        writer.WriteStartObject();
        // 遍历所有属性,跳过CustomFields
        foreach (var prop in contract.Properties.Where(p => p.PropertyName != nameof(RecurrenceInfo.CustomFields)))
        {
            if (prop.Ignored || !prop.Readable) continue;
            var propValue = prop.ValueProvider.GetValue(value);
            if (propValue == null && serializer.NullValueHandling == NullValueHandling.Ignore) continue;
            
            writer.WritePropertyName(prop.PropertyName);
            serializer.Serialize(writer, propValue, prop.PropertyType);
        }
        writer.WriteEndObject();
    }

    public override RecurrenceInfo ReadJson(JsonReader reader, Type objectType, RecurrenceInfo existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jObj = JObject.Load(reader);
        // 反序列化前先移除CustomFields字段
        jObj.Remove(nameof(RecurrenceInfo.CustomFields));
        var result = hasExistingValue ? existingValue : new RecurrenceInfo();
        using var subReader = jObj.CreateReader();
        serializer.Populate(subReader, result);
        return result;
    }
}
  1. 给属性加标注即可
public class A
{
    [JsonProperty]
    [JsonConverter(typeof(RecurrenceInfoConverter))]
    public RecurrenceInfo B { get; set; }        
}

方案2:多场景复用的轻量配置

如果项目中多处用到 RecurrenceInfo,不想每个属性都加转换器,可以自定义契约解析器,只会影响 RecurrenceInfo 的 CustomFields 字段,不会干扰其他类型的序列化逻辑:

public class SkipCustomFieldsResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        if (property.DeclaringType == typeof(RecurrenceInfo) 
            && property.PropertyName == nameof(RecurrenceInfo.CustomFields))
        {
            property.Ignored = true;
        }
        return property;
    }
}

使用时仅需要在对应序列化/反序列化的位置传入配置即可,不需要全局注册:

var settings = new JsonSerializerSettings
{
    ContractResolver = new SkipCustomFieldsResolver()
};
// 序列化
var json = JsonConvert.SerializeObject(obj, settings);
// 反序列化
var result = JsonConvert.DeserializeObject<A>(json, settings);

方案3:最小改动临时方案

如果只需要快速解决反序列化报错问题,可以加全局错误处理,直接忽略该类异常,代码改动量最小:

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
    Error = (sender, args) =>
    {
        if (args.ErrorContext.Error is JsonSerializationException ex 
            && ex.Message.Contains("Cannot populate list type DevExpress.XtraScheduler.CustomFieldCollection"))
        {
            args.ErrorContext.Handled = true;
        }
    }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 21:57:02