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

无[DataContract]标记时Json.NET序列化基类私有字段的问题

问题根因

你自定义的ContractResolver无法序列化基类字段/属性的核心原因是:C# 中Type.GetProperties()和Type.GetFields()方法默认不会返回继承链上层基类定义的私有成员,仅会返回当前类型自身的所有成员、以及基类的公有/受保护成员。要导出全部字段需要递归遍历从当前类型到顶级基类的所有类型,逐一收集成员。

修正后的ContractResolver代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

public class MyContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var allMembers = new List<MemberInfo>();
        var currentType = type;
        // 递归遍历整个继承链,直到object类
        while (currentType != null && currentType != typeof(object))
        {
            // 收集当前类型的所有属性
            allMembers.AddRange(currentType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                .Where(p => p.CanRead && p.CanWrite));
            // 收集当前类型的所有字段
            allMembers.AddRange(currentType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
            
            currentType = currentType.BaseType;
        }

        // 转换为JsonProperty并去重
        var properties = allMembers
            .Select(m => m is PropertyInfo p 
                ? base.CreateProperty(p, memberSerialization) 
                : base.CreateProperty((FieldInfo)m, memberSerialization))
            .Distinct(JsonPropertyComparer.Instance)
            .ToList();

        foreach (var property in properties)
        {
            var ignored = ShouldPropertyBeIgnored(property);
            property.Ignored = ignored;
            property.Readable = !ignored;
            property.Writable = !ignored;
        }
            
        return properties;
    }

    // 实际包含自定义过滤逻辑
    private bool ShouldPropertyBeIgnored(JsonProperty property) => false;
}

使用方法

序列化时指定使用自定义的ContractResolver即可:

var derived = new Derived(10);
var settings = new JsonSerializerSettings
{
    ContractResolver = new MyContractResolver()
};
var serialized = JsonConvert.SerializeObject(derived, settings);
Console.WriteLine(serialized);

运行后输出结果为{"_field":10},符合预期序列化要求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 06:27:04