.NET C# Enum Json 在没有 newtonsoft 的情况下使用 EnumMember 值中的破折号反序列化

问题描述 投票:0回答:1

我正在使用

System.Text.Json.Serialization
我正在尝试反序列化一个在
EnumMember
CheckStatus
.

中带有破折号的成员
  [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
  public enum CheckStatus
  {
       [System.Runtime.Serialization.EnumMember(Value = "newFile")]
       NewFile,

       [System.Runtime.Serialization.EnumMember(Value = "check-status")]
       CheckStatus,
  }

我写了一个

BindModelAsync

   public class FileStatusModelBuilder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {

            var rawData = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).FirstValue;
            rawData = JsonSerializer.Serialize(rawData);
            CheckStatus result = JsonSerializer.Deserialize<CheckStatus>(rawData);
            bindingContext.Result = ModelBindingResult.Success(result);
            return Task.CompletedTask;
        }
    }

传入

newFile
时,绑定有效并将绑定到
NewFile
,但是一旦我使用
check-status
,我就会收到以下错误。

The JSON value could not be converted to [...].CheckStatus. Path: $ | LineNumber: 0 | BytePositionInLine: 15.

我不想使用

newtonsoft
但希望能够在
EnumMember
值中有一个带有破折号的枚举。

c# json .net serialization binding
1个回答
0
投票

System.Text.Json
似乎仍然不支持
System.Runtime.Serialization
(而且似乎不会,基于 this github issue),因此您可以实现自定义序列化程序,例如这个 github issue on the topic 中的解决方法:

[System.Text.Json.Serialization.JsonConverter(typeof(JsonStringEnumConverterEx<CheckStatus>))]
public enum CheckStatus
{
    [EnumMember(Value = "newFile")]
    NewFile,

    [EnumMember(Value = "check-status")]
    CheckStatus,
}

public class JsonStringEnumConverterEx<TEnum> : System.Text.Json.Serialization.JsonConverter<TEnum>
    where TEnum : struct, System.Enum
{

    private readonly Dictionary<TEnum, string> _enumToString = new();
    private readonly Dictionary<string, TEnum> _stringToEnum = new();
    private readonly Dictionary<int, TEnum> _numberToEnum = new();

    public JsonStringEnumConverterEx()
    {
        var type = typeof(TEnum);

        foreach (var value in Enum.GetValues<TEnum>())
        {
            var enumMember = type.GetMember(value.ToString())[0];
            var attr = enumMember.GetCustomAttributes(typeof(EnumMemberAttribute), false)
                .Cast<EnumMemberAttribute>()
                .FirstOrDefault();

            _stringToEnum.Add(value.ToString(), value);
            var num = Convert.ToInt32(type.GetField("value__")
                .GetValue(value));
            if (attr?.Value != null)
            {
                _enumToString.Add(value, attr.Value);
                _stringToEnum.Add(attr.Value, value);
                _numberToEnum.Add(num, value);
            }
            else
            {
                _enumToString.Add(value, value.ToString());
            }
        }
    }

    public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var type = reader.TokenType;
        if (type == JsonTokenType.String)
        {
            var stringValue = reader.GetString();
            if (_stringToEnum.TryGetValue(stringValue, out var enumValue))
            {
                return enumValue;
            }
        }
        else if (type == JsonTokenType.Number)
        {
            var numValue = reader.GetInt32();
            _numberToEnum.TryGetValue(numValue, out var enumValue);
            return enumValue;
        }

        return default;
    }

    public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(_enumToString[value]);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.