.NET C# Enum Json反序列化,在EnumMember值中使用破折号,而不使用newtonsoft [duplicate]

wpx232ag  于 2023-05-02  发布在  .NET
关注(0)|答案(1)|浏览(134)

此问题已在此处有答案

System.Text.Json: How do I specify a custom name for an enum value?(3个答案)
7天前关闭
我正在使用System.Text.Json.Serialization我试图反序列化一个在EnumMemberCheckStatus中带有破折号的成员。

[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值中能够有一个带破折号的枚举。

l7wslrjt

l7wslrjt1#

System.Text.Json似乎仍然不支持System.Runtime.Serialization(基于this github issue,它似乎不会支持),所以你可以实现自定义序列化器,例如这个github问题的解决方案:

[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]);
    }
}

相关问题