2013-04-18 70 views
8

我正在編寫一個JsonConverter來執行一些我需要在讀/寫上完成的轉換任務。特別是,我正在使用現有的序列化行爲,並在讀取/讀取這些附加屬性時添加一些附加屬性。在JsonConverter中遞歸地調用JsonSerializer

JsonConverter裏面,我想利用通過的JsonSerializer實例執行大部分轉換功能。但是,當我這樣做時,我最終進入一個遞歸循環,串行器調用我的轉換器,調用串入器調用轉換器等等。

我見過人們使用JsonConvert.SerializeObject,傳入串行器實例中的所有轉換器,但不包括this。但是,這對我不起作用,因爲它繞過了我在序列化器上完成的所有其他自定義,例如自定義合約解析器和DateTime處理。

有沒有一種方法,我可以:

  1. 使用串行實例傳遞給我,但不知何故排除我的轉換器,或
  2. 克隆傳給我的串行器(無需手動構建一個新的,通過屬性複製它的屬性)並刪除我的轉換器?

回答

0

這是一個非常普遍的問題。使用「JsonConvert.SerializeObject」不是一個壞主意。然而,在某些情況下(通常爲集合)可以使用的一種技巧是在寫入時將接口轉換爲接口,並在讀取時將反序列化轉換爲簡單的派生。

下面是一個簡單的轉換器,與可能已係列化爲一組KVPs,而不是看起來像一個對象字典優惠(顯示我的年齡在這裏:))

注「WriteJson」強制轉換成IDictionary的<ķ ,V>和「ReadJson」使用「DummyDictionary」。你最終得到的是正確的東西,但使用傳遞的序列化程序而不會引起遞歸。

/// <summary> 
/// Converts a <see cref="KeyValuePair{TKey,TValue}"/> to and from JSON. 
/// </summary> 
public class DictionaryAsKVPConverter<TKey, TValue> : JsonConverter 
{ 
    /// <summary> 
    /// Determines whether this instance can convert the specified object type. 
    /// </summary> 
    /// <param name="objectType">Type of the object.</param> 
    /// <returns> 
    ///  <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>. 
    /// </returns> 
    public override bool CanConvert(Type objectType) 
    { 
     if (!objectType.IsValueType && objectType.IsGenericType) 
      return (objectType.GetGenericTypeDefinition() == typeof(Dictionary<,>)); 

     return false; 
    } 

    /// <summary> 
    /// Writes the JSON representation of the object. 
    /// </summary> 
    /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> 
    /// <param name="value">The value.</param> 
    /// <param name="serializer">The calling serializer.</param> 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var dictionary = value as IDictionary<TKey, TValue>; 
     serializer.Serialize(writer, dictionary); 
    } 

    /// <summary> 
    /// Reads the JSON representation of the object. 
    /// </summary> 
    /// <param name="reader">The <see cref="JsonReader"/> to read from.</param> 
    /// <param name="objectType">Type of the object.</param> 
    /// <param name="existingValue">The existing value of object being read.</param> 
    /// <param name="serializer">The calling serializer.</param> 
    /// <returns>The object value.</returns> 
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     Dictionary<TKey, TValue> dictionary; 

     if (reader.TokenType == JsonToken.StartArray) 
     { 
      dictionary = new Dictionary<TKey, TValue>(); 
      reader.Read(); 
      while (reader.TokenType == JsonToken.StartObject) 
      { 
       var kvp = serializer.Deserialize<KeyValuePair<TKey, TValue>>(reader); 
       dictionary[kvp.Key] = kvp.Value; 
       reader.Read(); 
      } 
     } 
     else if (reader.TokenType == JsonToken.StartObject) 
      // Use DummyDictionary to fool JsonSerializer into not using this converter recursively 
      dictionary = serializer.Deserialize<DummyDictionary>(reader); 
     else 
      dictionary = new Dictionary<TKey, TValue>(); 

     return dictionary; 
    } 

    /// <summary> 
    /// Dummy to fool JsonSerializer into not using this converter recursively 
    /// </summary> 
    private class DummyDictionary : Dictionary<TKey, TValue> { } 
} 
-3

對不起,但也許我很困惑。我用這個方法對我的序列化對象:

using System; 
 
using Newtonsoft.Json; 
 

 
namespace Utilities 
 
{ 
 
    public static class serializer 
 
    { 
 
     public static string SerializeObject(object objectModel) { 
 
      return JsonConvert.SerializeObject(objectModel); 
 
     } 
 
     public static object DeserializeObject<T>(string jsonObject) 
 
     { 
 
      try 
 
      { 
 
       return JsonConvert.DeserializeObject<T>(jsonObject); 
 
      } 
 
      catch (Exception ex) { return null; } 
 
      
 
     } 
 
    } 
 
}

,我用這個代碼:

userLoged = (modelUser)serializer.DeserializeObject<modelUser>((string)Session["userLoged"]);

我希望這是有幫助的。

+1

這並不回答被問到的問題。問題不是「我如何使用'JsonConvert'序列化我的對象?」這是問如何避免從一個自定義的'JsonConverter'中的遞歸循環。請注意['JsonConvert'](http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonConvert.htm)和['JsonConverter'](http://www.newtonsoft.com/json/help/html /T_Newtonsoft_Json_JsonConverter.htm)是Json.Net中兩個完全不同的類。 –