4

I want to remove one enum value from my enum. But when deserializing JSON if that removed enum value found then it should select my choice of enum value instead of defaulting to None which is first value in my enum for backward compatibility.

Example:

public enum ExampleHotkeyType
{
    None,
    CaptureRegion,
    CaptureRegionWindow,
    CaptureRegionPolygon,
    CaptureRegionFreehand
}

I want to remove CaptureRegionWindow in this enum and when deserializing if CaptureRegionWindow found I want it to be assigned to CaptureRegion instead. That way it won't default to None.

I searched maybe I could set CaptureRegion enum value to have more than one name as attribute but couldn't find such thing.

What would be best way to handle this issue so my users setting won't reset?

Note: I'm using StringEnumConverter when serializing/deserializing.

Jaex
  • 4,204
  • 2
  • 34
  • 56

1 Answers1

1

Inheriting StringEnumConverter allowed me to have full control on it:

public class ExampleHotkeyTypeEnumConverter : StringEnumConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.String)
        {
            string enumText = reader.Value.ToString();

            if (!string.IsNullOrEmpty(enumText) && enumText.Equals("CaptureRegionWindow"))
            {
                return ExampleHotkeyType.CaptureRegion;
            }
        }

        return base.ReadJson(reader, objectType, existingValue, serializer);
    }
}

[JsonConverter(typeof(ExampleHotkeyTypeEnumConverter))]
public enum ExampleHotkeyType
{
    None,
    CaptureRegion,
    CaptureRegionWindow,
    CaptureRegionPolygon,
    CaptureRegionFreehand
}

If you would like to keep existing enum value then you can use this enum converter instead:

public class SafeStringEnumConverter : StringEnumConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        try
        {
            return base.ReadJson(reader, objectType, existingValue, serializer);
        }
        catch (JsonSerializationException)
        {
            return existingValue;
        }
    }
}
Jaex
  • 4,204
  • 2
  • 34
  • 56
  • 1
    As a generic solution I would suggest creating attribute similar to .NET `EnumMember` which would accept multiple values, then use it on deserialization stage - this way we can support arbitrary enums. Here is the converter that supports `EnumMember` attribute. https://gist.github.com/gubenkoved/999eb73e227b7063a67a50401578c3a7 – Eugene D. Gubenkov Apr 02 '17 at 07:27