2015-08-14 42 views
2

在我的WPF代碼中,我使用Newtonsoft.Json將json反序列化爲我的模型。首先,我收到一個Json字符串('json'),然後我將其解析爲'消息'。 (我想要反序列化的對象被包裝在json字符串中的「data」字段中)。Json.Net在使用我的JsonConverter前自行轉換

Activity message = JObject.Parse(json)["data"].ToObject<Activity>(); 

我的Activity類使用多個[JsonProperty]屬性來生成它的字段。其中之一是一個名爲'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(); 
    } 
} 

有什麼奇怪的,令人沮喪的是,我知道有「型」的JSON對象:「email_open」被反序列化ActivityType.Unsupported,即使我的轉換器應反序列化他們作爲EmailOpen。

調試所表現出來的問題是什麼: 的JSON田「字型」自動反序列化「email_open」作爲EmailOpen ,然後它是通過我的轉換器發送。 (這是因爲我的條件檢查下劃線,而EmailOpen.ToString()沒有一個。)


所以我的問題是:爲什麼它轉換沒有我的轉換器,我該如何阻止它?我只是希望它只使用我的轉換器

+1

難道不該'objectType.Equals(typeof運算(ActivityType)'(前面沒有'!')?(或者只是'objectType == typeof(ActivityType)')? – dbc

+0

@dbc我不希望它轉換,如果它已經是一個ActivityType。那是我試圖停止(沒有改變任何東西,因爲我發現,第一次轉換甚至沒有使用我的轉換器) – thefistopher

+0

作爲轉換你自己的轉換器的替代方法,請參見[如何裝飾JSON.NET StringEnumConverter](http:// stackoverflow.com/questions/22908204/howto-decorate-json-net-stringenumconverter)。 – dbc

回答

2

我認爲你的轉換器正在被調用 - 它只是不工作。問題是,您不是從JsonReader reader讀取新值,而是使用existingValue中的值。但是,第二個值是被反序列化的類中的預先存在的屬性值,而不是正在讀取的值。

您需要從Json.NET的StringEnumConverter的行中讀取讀者的值。下面是做一個版本,並通過繼承StringEnumConverter並通過從文件中讀取以便進一步處理的基類值處理您的枚舉的標準值:

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); 
    } 
} 
+0

哦,我明白了,你是對的,我誤以爲現有的價值已經預先轉換了價值。它可能是EmailOpen,因爲枚舉是不可空的,這是第一個選項(?)。無論如何,現在一切都很好,謝謝! – thefistopher

相關問題