如何将任何对象序列化为字符串?

时间:2016-05-25 22:20:35

标签: c# .net serialization json.net

由于角色<不时出现,我遇到了JSON序列化程序随机失败的问题。我无法确定它的来源,我希望 - 在例外情况下 - 使用不同的方法重新编译,这样我就可以看到有问题的对象的完整表示。有没有办法做到这一点?

我目前的代码:

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

1 个答案:

答案 0 :(得分:18)

没有万无一失的方法来序列化任何可能的c#对象。

相反,您有几种方法可以解决您的问题:

  1. 启用Json.NET跟踪。见Debugging with Serialization Tracing。这应该告诉您对象图中的问题发生在哪里。

  2. 不是使用JsonConvert.SerializeObject()进行序列化,如果使用JsonSerializer.Serialize()序列化并使用JsonTextWriter包裹StringWriter来写入字符串,则可以刷新编写器并记录部分序列化。这可能会让人知道问题出在哪里。

  3. 您可以尝试使用其他各种序列化程序进行序列化,如果有任何工作,请记录结果。

  4. 如果您的某个对象属性引发异常,则可能会尝试强制字段序列化。请参阅JSON.Net: Force serialization of all private fields and all fields in sub-classes

  5. 例如,将#1,#2和#3放在一起会产生以下方法:

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

    您可能会使用适当的日志记录方法替换最终Debug.WriteLine(),然后在应用程序代码中将JsonConvert.SerializeObject(data)替换为JsonSerializerExtensions.SerializeObject(data)