将json字符反序列化为枚举
Posted
技术标签:
【中文标题】将json字符反序列化为枚举【英文标题】:Deserialize json character as enumeration 【发布时间】:2013-09-04 06:40:13 【问题描述】:我有一个用 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"]
是否可以定义某种转换器,让我可以手动将字符解析为枚举值?
我尝试创建一个 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;
我确定我做错了,但找不到有关如何为单个字段执行此操作的文档...
我错过了什么?
【问题讨论】:
您能否发布一个具有CardType
属性的示例类,其中反序列化失败?
你能发布完整的枚举吗?我相信你不能像上面定义的那样声明枚举
被反序列化的类只有一个 CardType 属性来接收反序列化的值,除了声明之外没有任何内容。至于枚举值,这确实是ENUM的完整定义。 Card 类有一个 CardType 类型的属性,用于存储枚举类型值。
我收到此枚举的编译错误...这是在 java 中吗??
对不起,这是 C#,我应该在描述中指定会更新,对此感到抱歉
【参考方案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'
【讨论】:
哇,这看起来是一个理想的解决方案,而且效果很好,谢谢! 如何反序列化上面的?我在反序列化时遇到问题。例如:服务有这个枚举:[EnumMember(Value = "Contemp")] Contemporary = 'C',UI 代码有这个枚举:[EnumMember(Value = "Contemp")] Contemporary = 'C' 所以,在反序列化时,它找不到“当代”..有什么办法吗?或者只是将 Enum 和 Value 交换为 [EnumMember(Value = "ontemporary ")] Contemp = 'C',【参考方案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;
【讨论】:
是的,对不起,我错了,JSON 不是由序列化生成的,它是一个自定义 JSON 字符串,它使用 char 值而不是 int。请查看更新后的说明,感谢您的帮助!【参考方案3】:你可以只添加 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");
【讨论】:
【参考方案4】:这是使用自定义 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'
【讨论】:
以上是关于将json字符反序列化为枚举的主要内容,如果未能解决你的问题,请参考以下文章