首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JsonStringEnumConverter (System.Text.Json)支持空值吗?

JsonStringEnumConverter (System.Text.Json)支持空值吗?
EN

Stack Overflow用户
提问于 2019-12-17 18:11:21
回答 6查看 21.8K关注 0票数 19

我正在将代码从.NET Core2.x转换为.NET Core3.x(即使用本机库System.Text.Json)。在这样做的过程中,我遇到了一些问题,即以前对可空枚举的Newtonsoft.Json支持目前没有明确的迁移路径--看起来在.NET Core3.x中不支持它?

例如,使用Newtonsoft.Json,JSON转换器支持可空枚举,如下所示:

代码语言:javascript
复制
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的当前版本似乎不支持这一点。

如何解决这个问题?我不能迁移我的代码!

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2019-12-17 18:11:21

不幸的是,目前System.Text.Json中没有支持“开箱即用”来转换可空枚举。

然而,有一个解决方案,使用您自己的自定义转换器。(见下文)。

解决方案。使用自定义转换器。

您可以通过用自定义转换器对属性进行装饰来将其附加到属性:

代码语言:javascript
复制
// using System.Text.Json
[JsonConverter(typeof(StringNullableEnumConverter<UserStatus?>))]  // Note the '?'
public UserStatus? Status { get; set; }                            // Nullable Enum

这是转换器:

代码语言:javascript
复制
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());
    }
}

希望这会有所帮助,直到有本机支持,而不需要自定义转换器!

票数 17
EN

Stack Overflow用户

发布于 2021-04-16 14:42:39

现在5.0 - 用JsonConverterAttribute指定中支持它。

票数 8
EN

Stack Overflow用户

发布于 2021-02-16 16:05:28

我发现Svek的答案非常有用,但是我想让转换器与可空和非空枚举属性兼容。

为此,我对他的转换器进行了如下调整:

代码语言:javascript
复制
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());
    }
}

我还遗漏了一些我在解决方案中不需要的元素。希望这对外面的人有帮助。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59379896

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档