Sat*_*uru 6 c# json .net-core asp.net-core system.text.json
我正在使用最新的 .NET Core 3.1.1 开发 ASP.NET Core 应用程序,而System.Text.Json该应用程序之前使用的是Newtonsoft.Json. 按照 Microsoft迁移指南中的建议
,我已经完成了更改。另外,由于我的大多数枚举需要序列化为字符串,因此我已将 Startup.cs 配置ConfigureServices为全局使用JsonStringEnumConverter。
public void ConfigureServices(IServiceCollection services)
{
// lines omitted for brevity
services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
options.JsonSerializerOptions.IgnoreNullValues = true;
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
});
}
Run Code Online (Sandbox Code Playgroud)
但最近,在发布之后,我们意识到只有少数枚举通过我们的 API 以 json 形式给出。由于这些 API 是外部使用的,因此将数字更改为字符串可能是一件代价高昂的事情。
那么,有没有办法忽略某些枚举属性的通用性,例如带有属性的装饰[JsonIgnore]?
dbc*_*dbc 13
JsonStringEnumConverter实际上是 的子类JsonConverterFactory。它为序列化过程中遇到的JsonConverterEnum每个具体enum类型创建一个特定类型,然后将该特定enum类型序列化为字符串。
如果您不希望某些特定enum 类型被序列化为字符串,则可以使用装饰器模式并创建自己的转换器工厂来装饰 aJsonStringEnumConverter但阻止该enum类型被转换,如下所示:
public class OptOutJsonConverterFactory : JsonConverterFactoryDecorator
{
readonly HashSet<Type> optOutTypes;
public OptOutJsonConverterFactory(JsonConverterFactory innerFactory, params Type [] optOutTypes) : base(innerFactory) => this.optOutTypes = optOutTypes.ToHashSet();
public override bool CanConvert(Type typeToConvert) => base.CanConvert(typeToConvert) && !optOutTypes.Contains(typeToConvert);
}
public class JsonConverterFactoryDecorator : JsonConverterFactory
{
readonly JsonConverterFactory innerFactory;
public JsonConverterFactoryDecorator(JsonConverterFactory innerFactory)
{
if (innerFactory == null)
throw new ArgumentNullException(nameof(innerFactory));
this.innerFactory = innerFactory;
}
public override bool CanConvert(Type typeToConvert) => innerFactory.CanConvert(typeToConvert);
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) => innerFactory.CreateConverter(typeToConvert, options);
}
Run Code Online (Sandbox Code Playgroud)
然后在选项中使用它,如下所示:
options.Converters.Add(new OptOutJsonConverterFactory(new JsonStringEnumConverter(),
// Add here all enum types to serialize as integers:
typeof(SomeEnumNotToSerializeAsAString)
//, ...
));
Run Code Online (Sandbox Code Playgroud)
笔记:
如果维护要序列化为整数的枚举类型列表不方便,您可以使用某些自定义属性标记要序列化为整数的枚举类型,然后从内部排除标有该属性的类型CanConvert(CanConvert(Type typeToConvert)。
装饰器模式是必需的,因为JsonStringEnumConverter它是密封的。
模型小提琴#1在这里。
或者,如果您不希望将某些特定enum 属性序列化为字符串,则可以使用转换器将转换器应用于该属性,JsonConverterAttribute以忽略传入JsonSerializerOptions并生成默认序列化:
/// <summary>
/// Apply this converter to a property to force the property to be serialized with default options.
/// This converter can ONLY be applied to a property; setting it in options or on a type may cause a stack overflow exception!
/// </summary>
/// <typeparam name="T">the property's declared return type</typeparam>
public class SerializePropertyAsDefaultConverter<T> : JsonConverter<T>
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return JsonSerializer.Deserialize<T>(ref reader); // Ignore the incoming options!
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, value); // Ignore the incoming options!
}
}
Run Code Online (Sandbox Code Playgroud)
并将其应用到您的模型中,如下所示:
public class Model
{
public StringEnum StringEnum { get; set; }
[JsonConverter(typeof(SerializePropertyAsDefaultConverter<SomeEnumNotToSerializeAsAString>))]
public SomeEnumNotToSerializeAsAString SomeEnumNotToSerializeAsAString { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
笔记:
该解决方案利用了转换器的记录优先级:
[JsonConverter]应用于财产。- 添加到 Converters 集合中的转换器。
[JsonConverter]应用于自定义值类型或 POCO。
模型小提琴#2在这里。
| 归档时间: |
|
| 查看次数: |
3566 次 |
| 最近记录: |