我有一个用C#定义的枚举,我将它的值存储为字符,如下所示:
public enum CardType
{
Artist = 'A',
Contemporary = 'C',
Historical = 'H',
Musician = 'M',
Sports = 'S',
Writer = 'W'
}
我正在尝试使用JSON.NET反序列化,但传入的JSON是使用CHAR值(字符串)而不是枚举的int值编写的,如下所示:
[{"CardType","A"},{"CardType", "C"}]
是否可以定义某种转换器,允许我手动将char解析为枚举值?
我尝试创建一个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; }
}
}
我确定我做错了,但我找不到如何为单个字段执行此操作的文档......
我错过了什么?
答案 0 :(得分:28)
您无需自定义JsonConverter
即可使用内置StringEnumConverter
和EnumMemberAttribute
(来自System.Runtime.Serialization
程序集)的组合。
如果没有EnumMemberAttribute
,它会使用枚举名称,如艺术家,当代等,所以你需要将它的名称改为你的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'
}
答案 1 :(得分:6)
此代码完美无缺:
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; }
答案 2 :(得分:1)
你可以添加SerializerSettings.Converters.Add(new StringEnumConverter());
到您的BrowserJsonFormatter类
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");
}
}
答案 3 :(得分:0)
这是使用自定义 JsonConverter 对我有用的方法。我白天是一名 Java 开发人员,所以也许专家 C# 开发人员可以改进这一点或发现任何问题。
public class CharEnumConverter<T> : JsonConverter<T>
{
public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer)
{
char c = (char)(int)Enum.Parse(typeof(T), value.ToString());
writer.WriteValue(c + "");
}
public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer)
{
string stringValue = (string)reader.Value;
char charValue = stringValue[0];
int intValue = (int)charValue;
string intValueString = intValue + "";
if (Enum.IsDefined(typeof(T), intValue)) {
T result = (T)Enum.Parse(typeof(T), intValueString);
return result;
} else {
throw new Exception("Char value [" + charValue + "] is not defined for Enum [" + typeof(T).Name + "]");
}
}
}
我想作为 Json 读/写的枚举的示例用法。
[CharEnum]
public enum MyEnum {
NONE = 'A',
YAY = 'B'
}
public class MyClass {
[JsonConverter(typeof(CharEnumConverter<MyEnum>))]
public MyEnum myfield;
}
它将从 JSON 字符串中读取一个 'A' 到一个值为 NONE 的枚举字段中。 它会将值为 YAY 的枚举字段写入 JSON 字符串作为 'B'