Уничтожить 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");
}
}