Reputation: 575
In my C# code, I have an enum type that is going to be stored in MongoDB as string. In my C# code I have this type:
public enum Color
{
Unknown =0,
Red =1,
Blue =2,
Brown =3,
}
When in MongoDB string value is Red, Blue or Brown there is no problem but sometimes in DB there are other colours that are not included in my enum type like black, in this case, I expect the Color deserialized to Unknown but I get deserializing error indicates that black is not defined. Is there any way to handle this? I can not add every colour on my side and I can not change the enum type to any other type. I'm wondering how can I deserialize it to Unknown?
Upvotes: 3
Views: 1110
Reputation: 131
Another option is a custom generic enum serializer for the MongoDB driver (BSON), this will allow you to define a default value when registering the serializer
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;
}
}
You can use it like so
BsonSerializer.RegisterSerializer(typeof(CurrancyCode), new EnumSerializer<CurrancyCode>(CurrancyCode.GBP));
Upvotes: 0
Reputation: 5679
you will need a custom serializer like so:
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,
};
}
}
register it with the serializer registry during app startup like so:
BsonSerializer.RegisterSerializer(typeof(Color), new ColorSerializer());
done!
Upvotes: 1
Reputation: 2019
You can use a custom StringEnumConverter. This will return you default enum value
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;
}
}
}
You can use this in your enum like this
Then you can use it as follows:
[JsonConverter(typeof(SafeStringEnumConverter), Unknown)]
public enum Colors
{
Unknown=0,
Red =1,
Blue =2,
Brown =3
}
Upvotes: 1