Уничтожить json-символ в качестве перечисления

У меня есть перечисление, определенное с помощью С#, где я храню его как символы, например:

public enum CardType
{
    Artist = 'A',
    Contemporary = 'C',
    Historical = 'H',
    Musician = 'M',
    Sports = 'S',
    Writer = 'W'
}

Я пытаюсь десериализовать использование JSON.NET, но входящий JSON был написан с использованием значения CHAR (string) вместо значения int для перечисления, например:

[{"CardType","A"},{"CardType", "C"}]

Можно ли определить какой-то конвертер, который позволит мне вручную разобрать CHAR значение enum?

Я попытался создать JsonConverter, но не знаю, как это сделать, применяя его только к этому свойству, а не ко всему анализируемому объекту. вот что я пробовал:

public class EnumerationConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
        {
            return null;
        }

        int value = serializer.Deserialize<int>(reader);
        return (CardType)value;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType.IsSubclassOf(typeof(string));
    }
}

Логика может быть неправильной, и я могу это исправить, но проблема в том, что ReadJson() вообще не вызывается.

CanConvert есть, но он, кажется, вызывается для каждого свойства, а не только для одного свойства, которое я определил для него:

public class Card
{
            private CardType type;
        [JsonConverter(typeof(EnumerationConverter))]
        public CardType Type
        {
            get { return type; }
            set { type = value; }
        }
}

Я уверен, что сделал это неправильно, но мне трудно найти документацию о том, как это сделать для одного поля...

Что мне не хватает?

Ответы

Ответ 1

Вам не нужно настраивать JsonConverter, вы можете использовать встроенный StringEnumConverter с комбинацией EnumMemberAttribute (из сборки System.Runtime.Serialization).

Без EnumMemberAttribute он использует имена переименования, такие как Artist, Contemporary и т.д., поэтому вам нужно изменить имена с ним на ваши значения A, C и т.д.

Но это не самое приятное решение, потому что вы должны дважды повторять свои значения, но он работает:

[JsonConverter(typeof(StringEnumConverter))]
public enum CardType
{
    [EnumMember(Value = "A")]
    Artist = 'A',
    [EnumMember(Value = "C")]
    Contemporary = 'C',
    [EnumMember(Value = "H")]
    Historical = 'H',
    [EnumMember(Value = "M")]
    Musician = 'M',
    [EnumMember(Value = "S")]
    Sports = 'S',
    [EnumMember(Value = "W")]
    Writer = 'W'
}

Ответ 2

Этот код отлично работает:

CardType[] array = { CardType.Artist, CardType.Contemporary };
string s = JsonConvert.SerializeObject(array);
var array2 = JsonConvert.DeserializeObject<CardType[]>(s);

Обновление:
Как насчет готового StringEnumConverter:

[JsonConverter(typeof(StringEnumConverter))]
public CardType Type { get; set; }

Ответ 3

Вы можете просто добавить SerializerSettings.Converters.Add(новый StringEnumConverter());

для вашего браузераJsonFormatter class

public class BrowserJsonFormatter : JsonMediaTypeFormatter
{
    public BrowserJsonFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
        SerializerSettings.Formatting = Formatting.Indented;
        SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
        SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        SerializerSettings.Converters.Add(new EmptyToNullConverter());
        SerializerSettings.Converters.Add(new StringEnumConverter());
        //SerializerSettings.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate;
    }

    public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
    {
        base.SetDefaultContentHeaders(type, headers, mediaType);
        headers.ContentType = new MediaTypeHeaderValue("application/json");
    }
}