JsonStringEnumConverter (System.Text.Json) có hỗ trợ các giá trị null không?


8

Tôi đang chuyển mã từ .NET Core 2.x sang .NET Core 3.x (tức là sử dụng thư viện gốc System.Text.Json). Khi thực hiện điều này, tôi gặp phải một số vấn đề về cách Newtonsoft.Jsonhỗ trợ trước đây cho các enum nullable không có đường dẫn di chuyển rõ ràng vào lúc này --- có vẻ như nó không được hỗ trợ trong .NET Core 3.x?.

Ví dụ: bằng cách sử dụng Newtonsoft.Json, trình chuyển đổi JSON đã hỗ trợ các enum nullable, như vậy:

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
}

Phiên bản hiện tại của thư viện bản địa System.Text.Json, dường như không hỗ trợ điều này.

Làm thế nào để tôi giải quyết vấn đề này? Tôi không thể di chuyển mã của mình!


1
Hỗ trợ riêng cho hỗ trợ enum nullable trong JsonStringEnumConverter đang được theo dõi tại github.com/dotnet/corefx/issues/41307 .
Nitin Agarwal

@NitinAgarwal Hãy hy vọng nó sẽ được triển khai sớm!
Svek

Câu trả lời:


6

Thật không may, hiện tại không có hỗ trợ "ngoài luồng" System.Text.Jsonđể chuyển đổi các enum nullable.

Tuy nhiên, có một giải pháp bằng cách sử dụng trình chuyển đổi tùy chỉnh của riêng bạn . (xem bên dưới) .


Giải pháp. Sử dụng một công cụ chuyển đổi tùy chỉnh.

Bạn sẽ đính kèm có thể gắn nó vào tài sản của bạn bằng cách trang trí nó với trình chuyển đổi tùy chỉnh:

// using System.Text.Json
[JsonConverter(typeof(StringNullableEnumConverter<UserStatus?>))]  // Note the '?'
public UserStatus? Status { get; set; }                            // Nullable Enum

Đây là công cụ chuyển đổi:

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

Hy vọng rằng sẽ giúp cho đến khi có hỗ trợ riêng mà không cần một công cụ chuyển đổi tùy chỉnh!


1

Bạn sẽ có thể lấy lại hành vi ban đầu của mình bằng cách cài đặt nuget Newtonsoft và đặt mã này vào mã của bạn, tôi cho rằng bạn đang di chuyển một ứng dụng ASP:

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

1
Ý tưởng là sử dụng phiên bản mới hơn, "tốt hơn" (hiệu năng và khả năng tương thích của Microsoft trong thời gian dài) System.Text.Jsonđi kèm với ASP.NET Core 3.x. --- "Di cư" được đề cập là từ 2.x đến 3.x
Svek

@Svek Tôi có thể liên quan đến điều đó, tuy nhiên, tất cả chức năng Json Core sáng bóng mới đều có một số lỗ hổng, vì vậy, đến lúc ra, nhóm quyết định sử dụng phương pháp này, tôi hy vọng có thể hữu ích cho một số người khác vì nó trả lời câu hỏi của bạn hình thức ban đầu của nó - "làm thế nào để giải quyết vấn đề này?".
Michal Hosala
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.