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

.NET Standard转.NET Core 6双API兼容:Newtonsoft与System.Text.Json兼容问题

解决.NET Standard与.NET Core 6双API并行时JSON特性兼容问题

方案1:同时标记两种JSON特性

直接在模型属性上同时添加Newtonsoft.Json和System.Text.Json对应的特性,让两个序列化库都能识别规则。这种方式简单直接,适合迁移过渡阶段的小体量模型。

示例代码:

public class UserModel
{
    // 同时忽略两个序列化库的序列化
    [Newtonsoft.Json.JsonIgnore]
    [System.Text.Json.Serialization.JsonIgnore]
    public string InternalId { get; set; }

    // 同时指定驼峰命名的属性名
    [Newtonsoft.Json.JsonProperty("userName")]
    [System.Text.Json.Serialization.JsonPropertyName("userName")]
    public string UserName { get; set; }
}

方案2:配置序列化库识别对方特性

通过自定义解析逻辑,让每个序列化库能识别另一个库的特性,无需修改现有模型,适合已有大量模型的场景。

.NET Core 6 配置System.Text.Json识别Newtonsoft特性

在Program.cs中配置JsonOptions,自定义类型信息解析器来识别Newtonsoft的JsonIgnore和JsonProperty特性:

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        // 全局启用驼峰命名(可选)
        options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;

        options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver
        {
            Modifiers =
            {
                typeInfo =>
                {
                    foreach (var property in typeInfo.Properties)
                    {
                        // 识别Newtonsoft.Json.JsonIgnore
                        var newtonsoftIgnore = property.PropertyInfo?.GetCustomAttribute<Newtonsoft.Json.JsonIgnoreAttribute>();
                        if (newtonsoftIgnore != null)
                        {
                            property.ShouldSerialize = _ => false;
                        }

                        // 识别Newtonsoft.Json.JsonProperty的属性名
                        var newtonsoftProp = property.PropertyInfo?.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>();
                        if (newtonsoftProp != null && !string.IsNullOrEmpty(newtonsoftProp.PropertyName))
                        {
                            property.Name = newtonsoftProp.PropertyName;
                        }
                    }
                }
            }
        };
    });

.NET Standard 配置Newtonsoft.Json识别System.Text.Json特性

自定义ContractResolver来识别System.Text.Json的JsonIgnore和JsonPropertyName特性:

public class SystemTextJsonCompatibleResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        
        // 识别System.Text.Json.Serialization.JsonIgnore
        var systemIgnore = member.GetCustomAttribute<System.Text.Json.Serialization.JsonIgnoreAttribute>();
        if (systemIgnore != null)
        {
            property.Ignored = true;
        }

        // 识别System.Text.Json.Serialization.JsonPropertyName的属性名
        var systemPropName = member.GetCustomAttribute<System.Text.Json.Serialization.JsonPropertyNameAttribute>();
        if (systemPropName != null)
        {
            property.PropertyName = systemPropName.Name;
        }

        return property;
    }
}

// 使用配置
var jsonSettings = new Newtonsoft.Json.JsonSerializerSettings
{
    ContractResolver = new SystemTextJsonCompatibleResolver(),
    // 全局启用驼峰命名(可选)
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};

方案3:自定义共享特性+适配层

定义一套自己的JSON特性,在共享的.NET Standard项目中维护,然后分别为两个序列化库编写适配逻辑,让它们识别自定义特性。这种方式最优雅,避免重复代码,适合长期维护。

1. 定义共享特性

在共享项目中创建自定义特性:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class SharedJsonIgnoreAttribute : Attribute { }

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class SharedJsonPropertyNameAttribute : Attribute
{
    public string Name { get; }
    public SharedJsonPropertyNameAttribute(string name) => Name = name;
}

2. .NET Core 6 适配自定义特性

在Program.cs中配置System.Text.Json识别自定义特性:

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver
        {
            Modifiers =
            {
                typeInfo =>
                {
                    foreach (var property in typeInfo.Properties)
                    {
                        var sharedIgnore = property.PropertyInfo?.GetCustomAttribute<SharedJsonIgnoreAttribute>();
                        if (sharedIgnore != null)
                        {
                            property.ShouldSerialize = _ => false;
                        }

                        var sharedPropName = property.PropertyInfo?.GetCustomAttribute<SharedJsonPropertyNameAttribute>();
                        if (sharedPropName != null)
                        {
                            property.Name = sharedPropName.Name;
                        }
                    }
                }
            }
        };
    });

3. .NET Standard 适配自定义特性

自定义ContractResolver识别自定义特性:

public class SharedJsonContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        
        var sharedIgnore = member.GetCustomAttribute<SharedJsonIgnoreAttribute>();
        if (sharedIgnore != null)
        {
            property.Ignored = true;
        }

        var sharedPropName = member.GetCustomAttribute<SharedJsonPropertyNameAttribute>();
        if (sharedPropName != null)
        {
            property.PropertyName = sharedPropName.Name;
        }

        return property;
    }
}

// 使用配置
var jsonSettings = new Newtonsoft.Json.JsonSerializerSettings
{
    ContractResolver = new SharedJsonContractResolver()
};

方案选择建议

  • 小体量模型/临时过渡:选方案1,快速见效。
  • 已有大量模型不想修改:选方案2,通过配置兼容现有特性。
  • 长期维护/追求优雅:选方案3,统一特性标准,降低后续迁移成本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:25:13