.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
相关产品推荐
相关产品推荐

