Serialize an object to string
I have the following method to save an Object to a file:
// Save an object out to the disk
public static void SerializeObject<T>(this T toSerialize, String filename)
{
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
TextWriter textWriter = new StreamWriter(filename);
xmlSerializer.Serialize(textWriter, toSerialize);
textWriter.Close();
}
I confess I did not write it (I only converted it to a extension method that took a type parameter).
Now I need it to give the xml back to me as a string (rather than save it to a file). I am looking into it, but I have not figured it out yet.
I thought this might be really easy for someone familiar with these objects. If not I will figure it out eventually.
Solution 1:
Use a StringWriter
instead of a StreamWriter
:
public static string SerializeObject<T>(this T toSerialize)
{
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
using(StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, toSerialize);
return textWriter.ToString();
}
}
Note, it is important to use toSerialize.GetType()
instead of typeof(T)
in XmlSerializer constructor: if you use the first one the code covers all possible subclasses of T
(which are valid for the method), while using the latter one will fail when passing a type derived from T
.
Here is a link with some example code that motivate this statement, with XmlSerializer
throwing an Exception
when typeof(T)
is used, because you pass an instance of a derived type to a method that calls SerializeObject that is defined in the derived type's base class: http://ideone.com/1Z5J1.
Also, Ideone uses Mono to execute code; the actual Exception
you would get using the Microsoft .NET runtime has a different Message
than the one shown on Ideone, but it fails just the same.
Solution 2:
Serialize and Deserialize XML/JSON (SerializationHelper.cs
):
using Newtonsoft.Json;
using System.IO;
using System.Xml.Serialization;
namespace MyProject.Helpers
{
public static class SerializationHelper
{
public static T DeserializeXml<T>(this string toDeserialize)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (StringReader textReader = new StringReader(toDeserialize))
{
return (T)xmlSerializer.Deserialize(textReader);
}
}
public static string SerializeXml<T>(this T toSerialize)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, toSerialize);
return textWriter.ToString();
}
}
public static T DeserializeJson<T>(this string toDeserialize)
{
return JsonConvert.DeserializeObject<T>(toDeserialize);
}
public static string SerializeJson<T>(this T toSerialize)
{
return JsonConvert.SerializeObject(toSerialize);
}
}
}
Solution 3:
I know this is not really an answer to the question, but based on the number of votes for the question and the accepted answer, I suspect the people are actually using the code to serialize an object to a string.
Using XML serialization adds unnecessary extra text rubbish to the output.
For the following class
public class UserData
{
public int UserId { get; set; }
}
it generates
<?xml version="1.0" encoding="utf-16"?>
<UserData xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<UserId>0</UserId>
</UserData>
Better solution is to use JSON serialization (one of the best is Json.NET). To serialize an object:
var userData = new UserData {UserId = 0};
var userDataString = JsonConvert.SerializeObject(userData);
To deserialize an object:
var userData = JsonConvert.DeserializeObject<UserData>(userDataString);
The serialized JSON string would look like:
{"UserId":0}
Solution 4:
Code Safety Note
Regarding the accepted answer, it is important to use toSerialize.GetType()
instead of typeof(T)
in XmlSerializer
constructor: if you use the first one the code covers all possible scenarios, while using the latter one fails sometimes.
Here is a link with some example code that motivate this statement, with XmlSerializer
throwing an Exception when typeof(T)
is used, because you pass an instance of a derived type to a method that calls SerializeObject<T>()
that is defined in the derived type's base class: http://ideone.com/1Z5J1. Note that Ideone uses Mono to execute code: the actual Exception you would get using the Microsoft .NET runtime has a different Message than the one shown on Ideone, but it fails just the same.
For the sake of completeness I post the full code sample here for future reference, just in case Ideone (where I posted the code) becomes unavailable in the future:
using System;
using System.Xml.Serialization;
using System.IO;
public class Test
{
public static void Main()
{
Sub subInstance = new Sub();
Console.WriteLine(subInstance.TestMethod());
}
public class Super
{
public string TestMethod() {
return this.SerializeObject();
}
}
public class Sub : Super
{
}
}
public static class TestExt {
public static string SerializeObject<T>(this T toSerialize)
{
Console.WriteLine(typeof(T).Name); // PRINTS: "Super", the base/superclass -- Expected output is "Sub" instead
Console.WriteLine(toSerialize.GetType().Name); // PRINTS: "Sub", the derived/subclass
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
StringWriter textWriter = new StringWriter();
// And now...this will throw and Exception!
// Changing new XmlSerializer(typeof(T)) to new XmlSerializer(subInstance.GetType());
// solves the problem
xmlSerializer.Serialize(textWriter, toSerialize);
return textWriter.ToString();
}
}
Solution 5:
My 2p...
string Serialise<T>(T serialisableObject)
{
var xmlSerializer = new XmlSerializer(serialisableObject.GetType());
using (var ms = new MemoryStream())
{
using (var xw = XmlWriter.Create(ms,
new XmlWriterSettings()
{
Encoding = new UTF8Encoding(false),
Indent = true,
NewLineOnAttributes = true,
}))
{
xmlSerializer.Serialize(xw,serialisableObject);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
}