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

如何在System.Text.Json序列化时按场景指定包含或排除的类属性

System.Text.Json 动态选择序列化属性的实现方案

System.Text.Json 原生提供了等价于 Newtonsoft 中 ContractResolver 的能力,不需要引入额外的序列化库,根据你使用的 .NET 版本可以选择以下两种实现方案:

方案1:.NET 7+ 自定义 JsonTypeInfoResolver(推荐)

.NET 7 开始官方提供了 DefaultJsonTypeInfoResolver 用来修改序列化元数据,你可以为不同场景自定义过滤规则,生成独立的序列化配置,互不干扰。

通用过滤扩展方法示例:

using System.Text.Json;
using System.Text.Json.Serialization.Metadata;

public static class JsonSerializationExtensions
{
    // 按属性名列表排除指定属性,生成对应序列化配置
    public static JsonSerializerOptions CreateExcludedOptions<T>(params string[] excludedProperties)
    {
        var options = new JsonSerializerOptions
        {
            // 可按需配置其他规则,比如驼峰命名
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        };
        var resolver = new DefaultJsonTypeInfoResolver();
        
        resolver.Modifiers.Add(typeInfo =>
        {
            if (typeInfo.Type != typeof(T)) return;
            // 移除需要排除的属性
            foreach (var prop in typeInfo.Properties.ToList())
            {
                if (excludedProperties.Contains(prop.Name, StringComparer.OrdinalIgnoreCase))
                {
                    typeInfo.Properties.Remove(prop);
                }
            }
        });
        
        options.TypeInfoResolver = resolver;
        return options;
    }
}

使用示例:

public class Foo
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
}

var foo = new Foo { Name = "测试", Age = 20, Address = "北京市" };
// 场景A:包含所有属性,直接序列化
var jsonA = JsonSerializer.Serialize(foo);
// 场景B:排除Name属性,使用自定义配置
var optionsB = JsonSerializationExtensions.CreateExcludedOptions<Foo>("Name");
var jsonB = JsonSerializer.Serialize(foo, optionsB);

方案2:兼容 .NET 6 及更低版本的实现

如果你的项目还在使用 .NET 6 或更早版本,可以通过自定义 JsonConverter 实现动态过滤:

public class DynamicPropertyConverter<T> : JsonConverter<T>
{
    private readonly HashSet<string> _excludedProps;

    public DynamicPropertyConverter(params string[] excludedProps)
    {
        _excludedProps = new HashSet<string>(excludedProps, StringComparer.OrdinalIgnoreCase);
    }

    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 反序列化逻辑可按需实现,这里直接使用默认反序列化
        return JsonSerializer.Deserialize<T>(ref reader, options);
    }

    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        foreach (var prop in typeof(T).GetProperties())
        {
            if (_excludedProps.Contains(prop.Name)) continue;
            var propValue = prop.GetValue(value);
            writer.WritePropertyName(options.PropertyNamingPolicy?.ConvertName(prop.Name) ?? prop.Name);
            JsonSerializer.Serialize(writer, propValue, prop.PropertyType, options);
        }
        writer.WriteEndObject();
    }
}

使用示例:

var optionsB = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    Converters = { new DynamicPropertyConverter<Foo>("Name") }
};
var jsonB = JsonSerializer.Serialize(foo, optionsB);

注意事项

  • 如果需要按包含逻辑指定属性,只需要把上述代码的排除判断改为包含判断,仅保留指定属性即可。
  • 方案2的自定义Converter适合简单平面对象场景,复杂嵌套对象、字段序列化的场景建议升级到.NET 7+使用TypeInfoResolver方案,避免重复处理序列化边缘逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 09:45:00