JsonStringEnumConverter(System.Text.Json)はnull値をサポートしますか?


8

.NET Core 2.xから.NET Core 3.xにコードをシフトしています(つまり、ネイティブライブラリを使用していますSystem.Text.Json)。これを行う際に、以前のNewtonsoft.Jsonnull可能列挙型のサポートには現時点で明確な移行パスがないという問題が発生しました-.NET Core 3.xではサポートされていないようです。

たとえばNewtonsoft.Json、JSONコンバーターはを使用して、次のようにnull可能な列挙型をサポートしました。

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これをサポートしていないようです。

この問題を解決するにはどうすればよいですか?コードを移行できません!


1
JsonStringEnumConverterのnull可能列挙型サポートのネイティブサポートは、github.com/dotnet/corefx/issues/41307で追跡されています
Nitin Agarwal

@NitinAgarwalそれがすぐに実装されることを願っています!
Svek

回答:


6

残念ながら、現在のところ、System.Text.Jsonnull可能列挙型を変換するための「そのままの」サポートはありません。

ただし、独自のカスタムコンバーターを使用した解決策があります(下記参照)


ソリューション。カスタムコンバーターを使用します。

あなたはそれをカスタムコンバータで飾ることによってあなたのプロパティに添付することができます:

// 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());
    }
}

カスタムコンバーターを必要とせずにネイティブサポートができるまでそれが役立つことを願っています!


1

Newtonsoft JSON nugetをインストールしてコードに配置することで、元の動作に戻すことができるはずです。ASPアプリを移行していると思います。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddNewtonsoftJson();
}

1
アイデアはSystem.Text.Json、ASP.NET Core 3.xに付属する新しい「より良い」(長期的にはパフォーマンスとMicrosoftの互換性)を使用することです。---言及された「移行」は2.xから3.xへ
Svek

@Svekこれに関連することはできますが、すべての新しい光沢のあるJson Core機能にはいくつかのギャップがあるため、しばらくの間、チームはこのアプローチを使用することを決定しました。その元の形-「この問題を解決する方法?」
ミカルホサラ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.