如何将任何对象序列化为字符串? [英] How to serialize ANY object into a string?

查看:106
本文介绍了如何将任何对象序列化为字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到一个问题,由于字符<不时出现,我的JSON序列化程序随机失败.我无法确定这是哪里来的,我想-例外-使用其他方法重新序列化,这样我就可以看到有问题的对象的完整表示.有什么办法吗?

I'm running into an issue where my JSON serializer is failing randomly due to the character < showing up from time to time. I can't nail down where this is coming from and I want to - on exception - reserialize using a different method so I can see a full representation of the offending object. Is there any way to do this?

我当前的代码:

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

推荐答案

没有万无一失的方法来序列化所有可能的c#对象.

There is no foolproof way to serialize any and every possible c# object.

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

Instead, you have a few ways to attack your problem:

  1. 打开Json.NET跟踪.请参见使用序列化跟踪进行调试.这应该可以告诉您问题在对象图中的何处发生.

  1. Turn on Json.NET tracing. See Debugging with Serialization Tracing. This should tell you where in your object graph the problem is occurring.

如果使用 JsonSerializer.Serialize() JsonConvert.SerializeObject()进行序列化>并使用 JsonTextWriter 包裹StringWriter写入字符串,则可以刷新编写器并记录部分序列化.这可能会给问题出在何处提供一个提示.

Rather than serializing with JsonConvert.SerializeObject(), if you serialize with JsonSerializer.Serialize() and write to a string using a JsonTextWriter wrapping a StringWriter, you can flush the writer and log the partial serialization. That may give some idea where the problem arises.

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

You can try serializing using various other serializers, and if any work, log the result.

如果您的对象属性之一引发异常,则可以尝试强制字段的序列化.参见 JSON.Net :强制序列化所有私有字段和子类中的所有字段.

If one of your object properties is throwing an exception, you might try to force serialization of fields instead. See JSON.Net: Force serialization of all private fields and all fields in sub-classes.

例如,将#1,#2和#3放在一起可得到以下方法:

For instance, putting #1, #2 and #3 together gives the following method:

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(),然后在应用程序代码中用JsonSerializerExtensions.SerializeObject(data)替换JsonConvert.SerializeObject(data).

You would likely replace the final Debug.WriteLine() with an appropriate logging method, then replace JsonConvert.SerializeObject(data) with JsonSerializerExtensions.SerializeObject(data) in your applications code.

这篇关于如何将任何对象序列化为字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆