2013-04-18 47 views
8

Tôi đang viết một JsonConverter để thực hiện một số tác vụ chuyển đổi mà tôi cần thực hiện khi đọc/ghi. Đặc biệt, tôi đang lấy hành vi serialization hiện có và tacking trên một số thuộc tính bổ sung trên ghi/đọc các thuộc tính bổ sung trên đọc.Gọi đệ quy JsonSerializer trong một JsonConverter

Bên trong JsonConverter, tôi muốn sử dụng phiên bản JsonSerializer đã qua để thực hiện phần lớn chức năng chuyển đổi. Tuy nhiên, khi tôi làm điều này, tôi kết thúc trong một vòng lặp đệ quy nơi serializer gọi vào bộ chuyển đổi của tôi mà gọi vào serializer mà các cuộc gọi vào bộ chuyển đổi và vv.

Tôi đã thấy mọi người làm những việc như sử dụng JsonConvert.SerializeObject, chuyển tất cả các trình biến đổi từ phiên bản nối tiếp ngoại trừthis. Tuy nhiên, điều đó sẽ không làm việc cho tôi vì nó bỏ qua tất cả các tùy chỉnh khác mà tôi đã thực hiện trên bộ nối tiếp của tôi, chẳng hạn như trình phân giải hợp đồng tùy chỉnh và xử lý DateTime.

Có cách nào tôi có thể:

  1. Sử dụng ví dụ serializer truyền cho tôi, nhưng bằng cách nào đó loại trừ chuyển đổi của tôi, hoặc
  2. Clone serializer trôi qua với tôi (không có tay xây dựng một cái mới và sao chép nó bất động sản theo tài sản) và loại bỏ chuyển đổi của tôi?

Trả lời

0

Đây là vấn đề rất phổ biến. Sử dụng "JsonConvert.SerializeObject" không phải là một ý tưởng tồi. Tuy nhiên, một thủ thuật có thể được sử dụng trong một số trường hợp (thường là các bộ sưu tập) là truyền đến giao diện khi viết và deserialize thành một đạo hàm đơn giản khi đọc.

Dưới đây là một công cụ chuyển đổi đơn giản mà giao dịch với các từ điển mà có thể đã được đăng như một bộ KVPs hơn là trông như một đối tượng (thể hiện độ tuổi của tôi ở đây :))

Note "WriteJson" phôi để IDictionary < K , V> và "ReadJson" sử dụng "DummyDictionary". Bạn kết thúc với điều đúng nhưng sử dụng serializer được thông qua mà không gây ra đệ quy.

/// <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

Xin lỗi, nhưng có thể tôi đang bối rối. Tôi sử dụng phương pháp này để serialize đối tượng của tôi:

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; } 
 
      
 
     } 
 
    } 
 
}

và tôi đã sử dụng mã này:

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

Tôi hy vọng điều này đã giúp ích.

+1

Điều này không trả lời câu hỏi đã được hỏi. Câu hỏi không phải là "Làm thế nào để tuần tự hóa đối tượng của tôi bằng cách sử dụng' JsonConvert'? " Nó đã hỏi làm thế nào để tránh một vòng lặp đệ quy từ bên trong một 'JsonConverter' tùy chỉnh. Lưu ý rằng ['JsonConvert'] (http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonConvert.htm) và [' JsonConverter'] (http://www.newtonsoft.com/json/help/html /T_Newtonsoft_Json_JsonConverter.htm) là hai lớp hoàn toàn khác nhau trong Json.Net. –