问题描述
在我的WPF代码中,我正在使用Newtonsoft.Json将json反序列化到我的模型中.首先,我收到一个Json字符串('json'),然后将其解析为'message'. (我要反序列化的对象包装在json字符串的数据"字段中).
In my WPF code, I'm using Newtonsoft.Json to deserialize json into my models. First, I receive a Json string ('json') which I then parse into 'message'. (The object I want to deserialize is wrapped in a "data" field in the json string).
Activity message = JObject.Parse(json)["data"].ToObject<Activity>();
我的Activity类使用几个[JsonProperty]属性来生成其字段.其中之一是一个称为"ActivityType"的枚举.
My Activity class uses several [JsonProperty] attributes to generate its fields. One of them is an enum called 'ActivityType'.
[JsonProperty("type")]
[JsonConverter(typeof(ActivityTypeConverter))]
public ActivityType Type { get; set; }
public enum ActivityType {
EmailOpen,
LinkClick,
Salesforce,
Unsupported
};
public class ActivityTypeConverter : JsonConverter {
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var rawString = existingValue.ToString().ToLower();
if (rawString.Contains("click"))
return ActivityType.LinkClick;
else if (rawString.Contains("salesforce"))
return ActivityType.Salesforce;
else if (rawString.Contains("email_open"))
return ActivityType.EmailOpen;
else
{
Console.WriteLine("unsupported " + rawString);
return ActivityType.Unsupported;
}
}
public override bool CanConvert(Type objectType)
{
return !objectType.Equals(typeof(ActivityType));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
奇怪和令人沮丧的是,我知道具有类型":"email_open"的json对象正在反序列化为ActivityType.不受支持,即使我的转换器应该将它们反序列化为EmailOpen.
What's bizarre and frustrating is that json objects which I know have "type":"email_open" are being deserialized as ActivityType.Unsupported, even though my converter should be deserializing them as EmailOpen.
调试已显示出问题所在:json字段类型"会自动将"email_open"反序列化为EmailOpen ,然后通过我的转换器发送. (然后中断,因为我的条件检查下划线,而EmailOpen.ToString()没有下划线.)
所以我的问题是:为什么没有转换器就进行转换,如何停止?我只希望它仅使用我的转换器
Debugging has shown what the problem is:the json field "type" is automatically deserializing "email_open" as EmailOpen and then it is sent through my converter. (It breaks then because my conditional checks for an underscore, while EmailOpen.ToString() doesn't have one.)
So my question then is: Why is it converting without my converter and how do I stop it? I just want it to only use my converter
推荐答案
我认为您的转换器正在被调用-它只是无法正常工作.问题在于,您正在使用existingValue
中的值,而不是从JsonReader reader
中读取新值.但是第二个值是要反序列化的类中的预先存在的属性值,而不是正在读取的值.
I think your converter is being called -- it's just not working. The problem is that, rather than reading the new value from the JsonReader reader
, you are using the value from the existingValue
. But this second value is the pre-existing property value in the class being deserialized, not the value being read.
您需要按照Json.NET的 StringEnumConverter
.这是一个实现此功能的版本,它还通过子类化StringEnumConverter
并将从文件中读取的值传递给基类以进行进一步处理,从而处理枚举的标准值:
You need to load the value from the reader along the lines of Json.NET's StringEnumConverter
. Here's a version that does that and also handles standard values of your enum by subclassing StringEnumConverter
and passing the value read from the file to the base class for further processing:
public class ActivityTypeConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
bool isNullable = (Nullable.GetUnderlyingType(objectType) != null);
Type type = (Nullable.GetUnderlyingType(objectType) ?? objectType);
if (reader.TokenType == JsonToken.Null)
{
if (!isNullable)
throw new JsonSerializationException();
return null;
}
var token = JToken.Load(reader);
if (token.Type == JTokenType.String)
{
var rawString = ((string)token).ToLower();
if (rawString.Contains("click"))
return ActivityType.LinkClick;
else if (rawString.Contains("salesforce"))
return ActivityType.Salesforce;
else if (rawString.Contains("email_open"))
return ActivityType.EmailOpen;
}
using (var subReader = token.CreateReader())
{
while (subReader.TokenType == JsonToken.None)
subReader.Read();
try
{
return base.ReadJson(subReader, objectType, existingValue, serializer); // Use base class to convert
}
catch (Exception ex)
{
return ActivityType.Unsupported;
}
}
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ActivityType);
}
}
这篇关于Json.Net在使用我的JsonConverter之前自行进行转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!