我正在将代码从.NET Core2.x转换为.NET Core3.x(即使用本机库System.Text.Json)。在这样做的过程中,我遇到了一些问题,即以前对可空枚举的Newtonsoft.Json支持目前没有明确的迁移路径--看起来在.NET Core3.x中不支持它?
例如,使用Newtonsoft.Json,JSON转换器支持可空枚举,如下所示:
public enum UserStatus
{
NotConfirmed,
Active,
Deleted
}
public class User
{
public string UserName { get; set; }
[JsonConverter(typeof(StringEnumConverter))] // using Newtonsoft.Json
public UserStatus? Status { get; set; } // Nullable Enum
}本机库
System.Text.Json的当前版本似乎不支持这一点。
如何解决这个问题?我不能迁移我的代码!
发布于 2019-12-17 18:11:21
不幸的是,目前System.Text.Json中没有支持“开箱即用”来转换可空枚举。
然而,有一个解决方案,使用您自己的自定义转换器。(见下文)。
解决方案。使用自定义转换器。
您可以通过用自定义转换器对属性进行装饰来将其附加到属性:
// using System.Text.Json
[JsonConverter(typeof(StringNullableEnumConverter<UserStatus?>))] // Note the '?'
public UserStatus? Status { get; set; } // Nullable Enum这是转换器:
public class StringNullableEnumConverter<T> : JsonConverter<T>
{
private readonly JsonConverter<T> _converter;
private readonly Type _underlyingType;
public StringNullableEnumConverter() : this(null) { }
public StringNullableEnumConverter(JsonSerializerOptions options)
{
// for performance, use the existing converter if available
if (options != null)
{
_converter = (JsonConverter<T>)options.GetConverter(typeof(T));
}
// cache the underlying type
_underlyingType = Nullable.GetUnderlyingType(typeof(T));
}
public override bool CanConvert(Type typeToConvert)
{
return typeof(T).IsAssignableFrom(typeToConvert);
}
public override T Read(ref Utf8JsonReader reader,
Type typeToConvert, JsonSerializerOptions options)
{
if (_converter != null)
{
return _converter.Read(ref reader, _underlyingType, options);
}
string value = reader.GetString();
if (String.IsNullOrEmpty(value)) return default;
// for performance, parse with ignoreCase:false first.
if (!Enum.TryParse(_underlyingType, value,
ignoreCase: false, out object result)
&& !Enum.TryParse(_underlyingType, value,
ignoreCase: true, out result))
{
throw new JsonException(
$"Unable to convert \"{value}\" to Enum \"{_underlyingType}\".");
}
return (T)result;
}
public override void Write(Utf8JsonWriter writer,
T value, JsonSerializerOptions options)
{
writer.WriteStringValue(value?.ToString());
}
}希望这会有所帮助,直到有本机支持,而不需要自定义转换器!
发布于 2021-04-16 14:42:39
现在5.0 - 用JsonConverterAttribute指定中支持它。
发布于 2021-02-16 16:05:28
我发现Svek的答案非常有用,但是我想让转换器与可空和非空枚举属性兼容。
为此,我对他的转换器进行了如下调整:
public class JsonNullableEnumStringConverter<TEnum> : JsonConverter<TEnum>
{
private readonly bool _isNullable;
private readonly Type _enumType;
public JsonNullableEnumStringConverter() {
_isNullable = Nullable.GetUnderlyingType(typeof(TEnum)) != null;
// cache the underlying type
_enumType = _isNullable ?
Nullable.GetUnderlyingType(typeof(TEnum)) :
typeof(TEnum);
}
public override TEnum Read(ref Utf8JsonReader reader,
Type typeToConvert, JsonSerializerOptions options)
{
var value = reader.GetString();
if (_isNullable && string.IsNullOrEmpty(value))
return default; //It's a nullable enum, so this returns null.
else if (string.IsNullOrEmpty(value))
throw new InvalidEnumArgumentException(
$"A value must be provided for non-nullable enum property of type {typeof(TEnum).FullName}");
// for performance, parse with ignoreCase:false first.
if (!Enum.TryParse(_enumType, value, false, out var result)
&& !Enum.TryParse(_enumType, value, true, out result))
{
throw new JsonException(
$"Unable to convert \"{value}\" to Enum \"{_enumType}\".");
}
return (TEnum)result;
}
public override void Write(Utf8JsonWriter writer,
TEnum value, JsonSerializerOptions options)
{
writer.WriteStringValue(value?.ToString());
}
}我还遗漏了一些我在解决方案中不需要的元素。希望这对外面的人有帮助。
https://stackoverflow.com/questions/59379896
复制相似问题