我正在使用
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
值中有一个带有破折号的枚举。
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]);
}
}