2016-05-25 23 views
7

Si è verificato un problema in cui il serializzatore JSON non funziona in modo casuale a causa del carattere < visualizzato di volta in volta. Non riesco a capire da dove viene questo e voglio - su eccezioni - resettializzare usando un metodo diverso in modo da poter vedere una rappresentazione completa dell'oggetto offensivo. C'è un modo per fare questo?Come serializzare QUALSIASI oggetto in una stringa?

mio codice corrente:

// data is of type 'object' 
serialized = JsonConvert.SerializeObject(data, new JsonSerializerSettings() { 
    Error = delegate(object sender, ErrorEventArgs args) { 
     // reserialize here and output object so I know what the heck is going on 
    } 
}) 
+0

Bene si potrebbe provare ['JavaScriptSerializer'] (https://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer%28v=vs.110%29.aspx). Disponi dell'output 'ToString()' dell'eccezione incluso il messaggio e il traceback? – dbc

+0

[Debugging with Serialization Tracing] (http://www.newtonsoft.com/json/help/html/SerializationTracing.htm) potrebbe essere d'aiuto. – dbc

risposta

18

Non esiste un modo infallibile per serializzare ogni e qualsiasi possibile oggetto C#.

invece, avete un paio di modi per attaccare il problema:

  1. Accendere Json.NET tracciato. Vedi Debugging with Serialization Tracing. Questo dovrebbe dirti dove si trova il problema nel grafico degli oggetti.

  2. Piuttosto che la serializzazione con JsonConvert.SerializeObject(), se si serializzare con JsonSerializer.Serialize() e scrivere in una stringa utilizzando un JsonTextWriter avvolgendo un StringWriter, è possibile svuotare lo scrittore e registrare la serializzazione parziale. Questo potrebbe dare un'idea di dove sorge il problema.

  3. È possibile provare la serializzazione utilizzando vari altri serializzatori e, in caso di problemi, registrare il risultato.

  4. Se una delle proprietà dell'oggetto genera un'eccezione, è possibile provare a forzare la serializzazione dei campi. Vedi JSON.Net: Force serialization of all private fields and all fields in sub-classes.

Per esempio, mettendo # 1, # 2 e # 3 insieme ha pronunciato la seguente metodo:

public static class JsonSerializerExtensions 
{ 
    public static string SerializeObject(object obj, JsonSerializerSettings settings = null) 
    { 
     settings = settings ?? new JsonSerializerSettings(); 

     var sb = new StringBuilder(); 
     using (var writer = new StringWriter(sb)) 
     using (var jsonWriter = new JsonTextWriter(writer)) 
     { 
      var oldError = settings.Error; 
      var oldTraceWriter = settings.TraceWriter; 
      var oldFormatting = settings.Formatting; 
      try 
      { 
       settings.Formatting = Newtonsoft.Json.Formatting.Indented; 
       if (settings.TraceWriter == null) 
        settings.TraceWriter = new MemoryTraceWriter(); 
       settings.Error = oldError + delegate(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args) 
       { 
        jsonWriter.Flush(); 

        var logSb = new StringBuilder(); 
        logSb.AppendLine("Serialization error: "); 
        logSb.Append("Path: ").Append(args.ErrorContext.Path).AppendLine(); 
        logSb.Append("Member: ").Append(args.ErrorContext.Member).AppendLine(); 
        logSb.Append("OriginalObject: ").Append(args.ErrorContext.OriginalObject).AppendLine(); 
        logSb.AppendLine("Error: ").Append(args.ErrorContext.Error).AppendLine(); 
        logSb.AppendLine("Partial serialization results: ").Append(sb).AppendLine(); 
        logSb.AppendLine("TraceWriter contents: ").Append(settings.TraceWriter).AppendLine(); 

        logSb.AppendLine("JavaScriptSerializer serialization: "); 
        try 
        { 
         logSb.AppendLine(new JavaScriptSerializer().Serialize(obj)); 
        } 
        catch (Exception ex) 
        { 
         logSb.AppendLine("Failed, error: ").AppendLine(ex.ToString()); 
        } 

        logSb.AppendLine("XmlSerializer serialization: "); 
        try 
        { 
         logSb.AppendLine(obj.GetXml()); 
        } 
        catch (Exception ex) 
        { 
         logSb.AppendLine("Failed, error: ").AppendLine(ex.ToString()); 
        } 

        logSb.AppendLine("BinaryFormatter serialization: "); 
        try 
        { 
         logSb.AppendLine(BinaryFormatterExtensions.ToBase64String(obj)); 
        } 
        catch (Exception ex) 
        { 
         logSb.AppendLine("Failed, error: ").AppendLine(ex.ToString()); 
        } 

        Debug.WriteLine(logSb); 
       }; 
       var serializer = JsonSerializer.CreateDefault(settings); 
       serializer.Serialize(jsonWriter, obj); 
      } 
      finally 
      { 
       settings.Error = oldError; 
       settings.TraceWriter = oldTraceWriter; 
       settings.Formatting = oldFormatting; 
      } 
     } 

     return sb.ToString(); 
    } 
} 

public static class XmlSerializerExtensions 
{ 
    public static T LoadFromXML<T>(this string xmlString) 
    { 
     using (StringReader reader = new StringReader(xmlString)) 
     { 
      return (T)new XmlSerializer(typeof(T)).Deserialize(reader); 
     } 
    } 

    public static string GetXml<T>(this T obj) 
    { 
     using (var textWriter = new StringWriter()) 
     { 
      var settings = new XmlWriterSettings() { Indent = true, IndentChars = " " }; 
      using (var xmlWriter = XmlWriter.Create(textWriter, settings)) 
       new XmlSerializer(obj.GetType()).Serialize(xmlWriter, obj); 
      return textWriter.ToString(); 
     } 
    } 
} 

public static class BinaryFormatterExtensions 
{ 
    public static string ToBase64String<T>(T obj) 
    { 
     using (var stream = new MemoryStream()) 
     { 
      new BinaryFormatter().Serialize(stream, obj); 
      return Convert.ToBase64String(stream.GetBuffer(), 0, checked((int)stream.Length)); // Throw an exception on overflow. 
     } 
    } 

    public static T FromBase64String<T>(string data) 
    { 
     return FromBase64String<T>(data, null); 
    } 

    public static T FromBase64String<T>(string data, BinaryFormatter formatter) 
    { 
     using (var stream = new MemoryStream(Convert.FromBase64String(data))) 
     { 
      formatter = (formatter ?? new BinaryFormatter()); 
      var obj = formatter.Deserialize(stream); 
      if (obj is T) 
       return (T)obj; 
      return default(T); 
     } 
    } 
} 

Si sarebbe probabilmente sostituire il finale Debug.WriteLine() con un metodo di registrazione appropriato, quindi sostituire JsonConvert.SerializeObject(data) con JsonSerializerExtensions.SerializeObject(data) nel codice delle tue applicazioni.

+0

Questa domanda/risposta è stata discussa su meta: http://meta.stackoverflow.com/questions/323819/someone-immediately-answered-my-question-with-a-very-useful-response-i-want-it – user000001

Problemi correlati