2013-04-18 13 views
8

Sto scrivendo un JsonConverter per eseguire alcune attività di conversione che ho bisogno di eseguire su lettura/scrittura. In particolare, sto prendendo il comportamento di serializzazione esistente e virando su alcune proprietà aggiuntive per scrivere/leggere quelle proprietà aggiuntive in lettura.Chiamare in modo ricorsivo JsonSerializer in un JsonConverter

All'interno dello JsonConverter, mi piacerebbe utilizzare l'istanza passata JsonSerializer per eseguire la maggior parte delle funzionalità di conversione. Tuttavia, quando faccio questo, finisco in un ciclo ricorsivo in cui il serializzatore chiama nel mio convertitore che chiama nel serializzatore che chiama nel convertitore ed ecc.

Ho visto persone fare cose come l'uso JsonConvert.SerializeObject, passando tutti i convertitori dall'istanza serializzatore eccettothis. Tuttavia, questo non funzionerà per me perché ignora tutte le altre personalizzazioni che ho fatto sul mio serializzatore, come il resolver del contratto personalizzato e la gestione dello DateTime.

C'è un modo che può:

  1. Utilizzare l'istanza serializzatore passato a me, ma in qualche modo esclude mio convertitore, o
  2. Clone il serializzatore passato a me (senza costruire manualmente una nuova e copiandolo proprietà per proprietà) e rimuovi il mio convertitore?

risposta

0

Questo è un problema molto comune. L'utilizzo di "JsonConvert.SerializeObject" non è una cattiva idea. Tuttavia, un trucco che può essere utilizzato in alcune circostanze (in genere raccolte) consiste nel trasmettere all'interfaccia durante la scrittura e la deserializzazione in una derivata semplice durante la lettura.

Qui di seguito è un semplice convertitore che si occupa di dizionari che potrebbero essere stati serializzati come un insieme di KVPS piuttosto che guardare come un oggetto (mostrando la mia età qui :))

Nota "WriteJson" calchi di IDictionary < K , V> e "ReadJson" utilizza "DummyDictionary". Finisci con la cosa giusta ma usi il serializzatore passato senza causare la ricorsione.

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

Mi dispiace, ma forse sono confuso. Ho usato questo metodo per serializzare miei oggetti:

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

e ho usato di questo codice:

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

Spero che questo sia stato utile.

+1

Questo non risponde alla domanda che è stata posta. La domanda non era "Come serializzo il mio oggetto usando' JsonConvert'? " Stava chiedendo come evitare un ciclo ricorsivo all'interno di un 'JsonConverter 'personalizzato. Si noti che ['JsonConvert'] (http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonConvert.htm) e [' JsonConverter'] (http://www.newtonsoft.com/json/help/html /T_Newtonsoft_Json_JsonConverter.htm) sono due classi completamente diverse in Json.Net. –

Problemi correlati