我正在使用最新的.NET Core 3.1.1和以前使用System.Text.Json
的Newtonsoft.Json
开发ASP.NET Core应用程序。按照Microsoft Migration guide的建议我已完成更改。另外,由于我的大多数枚举都需要序列化为String,因此我已将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;
});
}
但是最近,在发布之后,我们意识到通过我们的API在json中只给出了几个枚举作为数字。由于这些API是在外部使用的,因此将数字更改为字符串可能是一项昂贵的工作。
因此,有没有办法忽略某些枚举属性的通用性,例如带有[JsonIgnore]
属性的修饰?
JsonStringEnumConverter
实际上是JsonStringEnumConverter
的子类。它为序列化过程中遇到的每种具体的JsonConverterFactory
类型生成一个特定的JsonConverterFactory
,进而将特定的JsonConverterEnum
类型序列化为字符串。
如果您不希望将某些特定的JsonConverterEnum
type序列化为字符串,则可以使用enum
并创建自己的转换器工厂来装饰enum
,但防止enum
类型转换如下:
decorator pattern
然后在以下选项中使用它:
JsonStringEnumConverter
注意:
如果要维护将枚举类型序列化为整数的列表很不方便,则可以使用某些自定义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);
}
中排除带有该属性的类型。 >
需要装饰图案,因为options.Converters.Add(new OptOutJsonConverterFactory(new JsonStringEnumConverter(),
// Add here all enum types to serialize as integers:
typeof(SomeEnumNotToSerializeAsAString)
//, ...
));
已密封。
模型小提琴#1 attribute。
或者,如果您不希望将某些特定的CanConvert(CanConvert(Type typeToConvert)
property
JsonStringEnumConverter
将转换器应用于该属性,而忽略传入的here并生成默认值序列化:enum
并按如下所示将其应用于您的模型:
JsonConverterAttribute
注意:
此解决方案利用了JsonConverterAttribute
:
JsonSerializerOptions
应用于属性。- 已将转换器添加到Converters集合。
- [
/// <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! } }
应用于自定义值类型或POCO。
模型小提琴#2 public class Model
{
public StringEnum StringEnum { get; set; }
[JsonConverter(typeof(SerializePropertyAsDefaultConverter<SomeEnumNotToSerializeAsAString>))]
public SomeEnumNotToSerializeAsAString SomeEnumNotToSerializeAsAString { get; set; }
}
。>>