Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serialize ANY object into a string?

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?

My current code:

// 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
    }
})
like image 238
RobVious Avatar asked May 25 '16 22:05

RobVious


People also ask

How do you serialize an object to a string?

To serialize an object to a string, we can use the base 64 encodings. We can implement the serialization by creating two classes, one class will implement the Serializable class, and the other class will be used to create the object of the Serializable class and serialize it.

How do you turn an object into a string?

Stringify a JavaScript ObjectUse the JavaScript function JSON.stringify() to convert it into a string. const myJSON = JSON.stringify(obj); The result will be a string following the JSON notation.

Can we serialize string?

The String class and all the wrapper classes implement the java. io. Serializable interface by default. In the above example, Student class implements Serializable interface.


1 Answers

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

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

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

  2. 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.

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

  4. 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.

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

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.

like image 81
dbc Avatar answered Oct 12 '22 08:10

dbc