当C#端没有等效值时,我们如何处理Enum的反序列化错误?
How we can handle deserializing error of Enum when there is no equivalent value in C# side?
在我的 C# 代码中,我有一个枚举类型将作为字符串存储在 MongoDB 中。在我的 C# 代码中,我有这种类型:
public enum Color
{
Unknown =0,
Red =1,
Blue =2,
Brown =3,
}
当 MongoDB 中的字符串值为红色、蓝色或棕色时没有问题,但有时在 DB 中还有其他颜色未包含在我的枚举类型中,例如黑色,在这种情况下,我希望颜色反序列化为未知,但反序列化错误表明未定义黑色。有什么办法可以解决这个问题吗?我无法在我这边添加所有颜色,也无法将枚举类型更改为任何其他类型。我想知道如何将它反序列化为 Unknown?
您可以使用自定义 StringEnumConverter。这将 return 您的默认枚举值
public class SafeStringEnumConverter : StringEnumConverter
{
public object DefaultValue { get; }
public SafeStringEnumConverter(object defaultValue)
{
DefaultValue = defaultValue;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
try
{
return base.ReadJson(reader, objectType, existingValue, serializer);
}
catch
{
return DefaultValue;
}
}
}
您可以像这样在您的枚举中使用它
那你就可以这样使用了:
[JsonConverter(typeof(SafeStringEnumConverter), Unknown)]
public enum Colors
{
Unknown=0,
Red =1,
Blue =2,
Brown =3
}
您将需要像这样的自定义序列化程序:
public class ColorSerializer : SerializerBase<Color>
{
public override void Serialize(BsonSerializationContext ctx, BsonSerializationArgs args, Color value)
{
ctx.Writer.WriteString(value.ToString());
}
public override Color Deserialize(BsonDeserializationContext ctx, BsonDeserializationArgs args)
{
return
ctx.Reader.CurrentBsonType switch
{
MongoDB.Bson.BsonType.String => ctx.Reader.ReadString() switch
{
"Red" => Color.Red,
"Blue" => Color.Blue,
"Brown" => Color.Brown,
_ => Color.Unknown,
},
_ => Color.Unknown,
};
}
}
在应用程序启动期间将其注册到序列化程序注册表,如下所示:
BsonSerializer.RegisterSerializer(typeof(Color), new ColorSerializer());
完成!
另一个选项是 MongoDB 驱动程序 (BSON) 的自定义通用枚举序列化程序,这将允许您在注册序列化程序时定义默认值
public class EnumSerializer<T> : SerializerBase<T> where T : struct
{
public T DefaultValue { get; }
public EnumSerializer(T defaultValue)
{
DefaultValue = defaultValue;
}
public override void Serialize(BsonSerializationContext ctx, BsonSerializationArgs args, T value)
{
ctx.Writer.WriteString(value.ToString());
}
public override T Deserialize(BsonDeserializationContext ctx, BsonDeserializationArgs args)
{
if (ctx.Reader.CurrentBsonType == MongoDB.Bson.BsonType.Null)
{
ctx.Reader.ReadNull();
return DefaultValue;
}
if (ctx.Reader.CurrentBsonType == MongoDB.Bson.BsonType.String)
{
var value = ctx.Reader.ReadString();
if (Enum.TryParse<T>(value, true, out var res))
return res;
}
return DefaultValue;
}
}
你可以这样使用它
BsonSerializer.RegisterSerializer(typeof(CurrancyCode), new EnumSerializer<CurrancyCode>(CurrancyCode.GBP));
在我的 C# 代码中,我有一个枚举类型将作为字符串存储在 MongoDB 中。在我的 C# 代码中,我有这种类型:
public enum Color
{
Unknown =0,
Red =1,
Blue =2,
Brown =3,
}
当 MongoDB 中的字符串值为红色、蓝色或棕色时没有问题,但有时在 DB 中还有其他颜色未包含在我的枚举类型中,例如黑色,在这种情况下,我希望颜色反序列化为未知,但反序列化错误表明未定义黑色。有什么办法可以解决这个问题吗?我无法在我这边添加所有颜色,也无法将枚举类型更改为任何其他类型。我想知道如何将它反序列化为 Unknown?
您可以使用自定义 StringEnumConverter。这将 return 您的默认枚举值
public class SafeStringEnumConverter : StringEnumConverter
{
public object DefaultValue { get; }
public SafeStringEnumConverter(object defaultValue)
{
DefaultValue = defaultValue;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
try
{
return base.ReadJson(reader, objectType, existingValue, serializer);
}
catch
{
return DefaultValue;
}
}
}
您可以像这样在您的枚举中使用它
那你就可以这样使用了:
[JsonConverter(typeof(SafeStringEnumConverter), Unknown)]
public enum Colors
{
Unknown=0,
Red =1,
Blue =2,
Brown =3
}
您将需要像这样的自定义序列化程序:
public class ColorSerializer : SerializerBase<Color>
{
public override void Serialize(BsonSerializationContext ctx, BsonSerializationArgs args, Color value)
{
ctx.Writer.WriteString(value.ToString());
}
public override Color Deserialize(BsonDeserializationContext ctx, BsonDeserializationArgs args)
{
return
ctx.Reader.CurrentBsonType switch
{
MongoDB.Bson.BsonType.String => ctx.Reader.ReadString() switch
{
"Red" => Color.Red,
"Blue" => Color.Blue,
"Brown" => Color.Brown,
_ => Color.Unknown,
},
_ => Color.Unknown,
};
}
}
在应用程序启动期间将其注册到序列化程序注册表,如下所示:
BsonSerializer.RegisterSerializer(typeof(Color), new ColorSerializer());
完成!
另一个选项是 MongoDB 驱动程序 (BSON) 的自定义通用枚举序列化程序,这将允许您在注册序列化程序时定义默认值
public class EnumSerializer<T> : SerializerBase<T> where T : struct
{
public T DefaultValue { get; }
public EnumSerializer(T defaultValue)
{
DefaultValue = defaultValue;
}
public override void Serialize(BsonSerializationContext ctx, BsonSerializationArgs args, T value)
{
ctx.Writer.WriteString(value.ToString());
}
public override T Deserialize(BsonDeserializationContext ctx, BsonDeserializationArgs args)
{
if (ctx.Reader.CurrentBsonType == MongoDB.Bson.BsonType.Null)
{
ctx.Reader.ReadNull();
return DefaultValue;
}
if (ctx.Reader.CurrentBsonType == MongoDB.Bson.BsonType.String)
{
var value = ctx.Reader.ReadString();
if (Enum.TryParse<T>(value, true, out var res))
return res;
}
return DefaultValue;
}
}
你可以这样使用它
BsonSerializer.RegisterSerializer(typeof(CurrancyCode), new EnumSerializer<CurrancyCode>(CurrancyCode.GBP));