将对象序列化为字符串

我有以下方法来保存一个对象到一个文件:

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

我承认这不是我写的(我只是把它转换成一个接受类型参数的扩展方法)。

现在我需要它把xml作为字符串返回给我(而不是保存到文件中)。我正在调查这件事,但我还没有弄清楚。

我想对于熟悉这些物体的人来说,这可能很简单。如果没有,我最终会弄清楚的。

473748 次浏览

使用StringWriter代替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();
}
}
注意,在XmlSerializer构造函数中使用toSerialize.GetType()而不是typeof(T)是很重要的:如果你使用第一个,代码将覆盖T的所有可能的子类(对该方法有效),而使用后一个在传递从T派生的类型时将失败。   下面是一些示例代码的链接,其中XmlSerializer在使用typeof(T)时抛出Exception,因为您将派生类型的实例传递给调用派生类型基类中定义的SerializeObject的方法:http://ideone.com/1Z5J1.

此外,Ideone使用Mono来执行代码;你使用Microsoft . net运行时得到的实际Exception与Ideone上显示的Message不同,但它同样失败。

代码安全说明

关于接受的答案,在XmlSerializer构造函数中使用toSerialize.GetType()而不是typeof(T)是很重要的:如果使用第一个构造函数,代码将覆盖所有可能的情况,而使用后一个构造函数有时会失败。

下面是一些示例代码的链接,其中XmlSerializer在使用typeof(T)时抛出异常,因为您将派生类型的实例传递给调用派生类型的基类中定义的SerializeObject<T>()的方法:http://ideone.com/1Z5J1注意,Ideone使用Mono来执行代码:使用Microsoft . net运行时获得的实际异常有一个与Ideone上显示的不同的消息,但它同样失败。

为了完整起见,我在这里发布了完整的代码样本,以供将来参考,以防将来Ideone(我发布代码的地方)变得不可用:

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

我知道这不是问题的真正答案,但根据问题的投票数和接受的答案,我怀疑人们实际上是在使用代码将对象序列化为字符串。

使用XML序列化会给输出增加不必要的额外文本垃圾。

对于下面的类

public class UserData
{
public int UserId { get; set; }
}

它生成

<?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>
更好的解决方案是使用JSON序列化(其中最好的是Json。网)。 序列化一个对象:

var userData = new UserData {UserId = 0};
var userDataString = JsonConvert.SerializeObject(userData);

反序列化一个对象:

var userData = JsonConvert.DeserializeObject<UserData>(userDataString);

序列化的JSON字符串看起来像这样:

{"UserId":0}

序列化和反序列化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);
}
}
}

我的2 p…

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

我无法使用xhafan建议的JSONConvert方法

在。net 4.5中,即使添加了“System.Web.”扩展程序集引用我仍然无法访问JSONConvert。

然而,一旦你添加了引用,你可以使用以下方法打印出相同的字符串:

JavaScriptSerializer js = new JavaScriptSerializer();
string jsonstring = js.Serialize(yourClassObject);

在极少数情况下,您可能希望实现自己的String序列化。

但这可能是一个的想法,除非你知道你在做什么。(例如用批处理文件序列化I/O)

类似这样的方法就可以达到目的(而且手动/批处理编辑也很容易),但是要注意应该做更多的检查,比如名称不包含换行符。

public string name {get;set;}
public int age {get;set;}


Person(string serializedPerson)
{
string[] tmpArray = serializedPerson.Split('\n');
if(tmpArray.Length>2 && tmpArray[0].Equals("#")){
this.name=tmpArray[1];
this.age=int.TryParse(tmpArray[2]);
}else{
throw new ArgumentException("Not a valid serialization of a person");
}
}


public string SerializeToString()
{
return "#\n" +
name + "\n" +
age;
}
public static string SerializeObject<T>(T objectToSerialize)
{
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
MemoryStream memStr = new MemoryStream();


try
{
bf.Serialize(memStr, objectToSerialize);
memStr.Position = 0;


return Convert.ToBase64String(memStr.ToArray());
}
finally
{
memStr.Close();
}
}


public static T DerializeObject<T>(string objectToDerialize)
{
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
byte[] byteArray = Convert.FromBase64String(objectToDerialize);
MemoryStream memStr = new MemoryStream(byteArray);


try
{
return (T)bf.Deserialize(memStr);
}
finally
{
memStr.Close();
}
}

(VB)

Public Function XmlSerializeObject(ByVal obj As Object) As String


Dim xmlStr As String = String.Empty


Dim settings As New XmlWriterSettings()
settings.Indent = False
settings.OmitXmlDeclaration = True
settings.NewLineChars = String.Empty
settings.NewLineHandling = NewLineHandling.None


Using stringWriter As New StringWriter()
Using xmlWriter__1 As XmlWriter = XmlWriter.Create(stringWriter, settings)


Dim serializer As New XmlSerializer(obj.[GetType]())
serializer.Serialize(xmlWriter__1, obj)


xmlStr = stringWriter.ToString()
xmlWriter__1.Close()
End Using


stringWriter.Close()
End Using


Return xmlStr.ToString
End Function


Public Function XmlDeserializeObject(ByVal data As [String], ByVal objType As Type) As Object


Dim xmlSer As New System.Xml.Serialization.XmlSerializer(objType)
Dim reader As TextReader = New StringReader(data)


Dim obj As New Object
obj = DirectCast(xmlSer.Deserialize(reader), Object)
Return obj
End Function

(c#)

public string XmlSerializeObject(object obj)
{
string xmlStr = String.Empty;
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = false;
settings.OmitXmlDeclaration = true;
settings.NewLineChars = String.Empty;
settings.NewLineHandling = NewLineHandling.None;


using (StringWriter stringWriter = new StringWriter())
{
using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, settings))
{
XmlSerializer serializer = new XmlSerializer( obj.GetType());
serializer.Serialize(xmlWriter, obj);
xmlStr = stringWriter.ToString();
xmlWriter.Close();
}
}
return xmlStr.ToString();
}


public object XmlDeserializeObject(string data, Type objType)
{
XmlSerializer xmlSer = new XmlSerializer(objType);
StringReader reader = new StringReader(data);


object obj = new object();
obj = (object)(xmlSer.Deserialize(reader));
return obj;
}

我觉得我需要分享这个被操纵的代码到接受的答案-因为我没有声誉,我无法评论。

using System;
using System.Xml.Serialization;
using System.IO;


namespace ObjectSerialization
{
public static class ObjectSerialization
{
// THIS: (C): https://stackoverflow.com/questions/2434534/serialize-an-object-to-string
/// <summary>
/// A helper to serialize an object to a string containing XML data of the object.
/// </summary>
/// <typeparam name="T">An object to serialize to a XML data string.</typeparam>
/// <param name="toSerialize">A helper method for any type of object to be serialized to a XML data string.</param>
/// <returns>A string containing XML data of the object.</returns>
public static string SerializeObject<T>(this T toSerialize)
{
// create an instance of a XmlSerializer class with the typeof(T)..
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());


// using is necessary with classes which implement the IDisposable interface..
using (StringWriter stringWriter = new StringWriter())
{
// serialize a class to a StringWriter class instance..
xmlSerializer.Serialize(stringWriter, toSerialize); // a base class of the StringWriter instance is TextWriter..
return stringWriter.ToString(); // return the value..
}
}


// THIS: (C): VPKSoft, 2018, https://www.vpksoft.net
/// <summary>
/// Deserializes an object which is saved to an XML data string. If the object has no instance a new object will be constructed if possible.
/// <note type="note">An exception will occur if a null reference is called an no valid constructor of the class is available.</note>
/// </summary>
/// <typeparam name="T">An object to deserialize from a XML data string.</typeparam>
/// <param name="toDeserialize">An object of which XML data to deserialize. If the object is null a a default constructor is called.</param>
/// <param name="xmlData">A string containing a serialized XML data do deserialize.</param>
/// <returns>An object which is deserialized from the XML data string.</returns>
public static T DeserializeObject<T>(this T toDeserialize, string xmlData)
{
// if a null instance of an object called this try to create a "default" instance for it with typeof(T),
// this will throw an exception no useful constructor is found..
object voidInstance = toDeserialize == null ? Activator.CreateInstance(typeof(T)) : toDeserialize;


// create an instance of a XmlSerializer class with the typeof(T)..
XmlSerializer xmlSerializer = new XmlSerializer(voidInstance.GetType());


// construct a StringReader class instance of the given xmlData parameter to be deserialized by the XmlSerializer class instance..
using (StringReader stringReader = new StringReader(xmlData))
{
// return the "new" object deserialized via the XmlSerializer class instance..
return (T)xmlSerializer.Deserialize(stringReader);
}
}


// THIS: (C): VPKSoft, 2018, https://www.vpksoft.net
/// <summary>
/// Deserializes an object which is saved to an XML data string.
/// </summary>
/// <param name="toDeserialize">A type of an object of which XML data to deserialize.</param>
/// <param name="xmlData">A string containing a serialized XML data do deserialize.</param>
/// <returns>An object which is deserialized from the XML data string.</returns>
public static object DeserializeObject(Type toDeserialize, string xmlData)
{
// create an instance of a XmlSerializer class with the given type toDeserialize..
XmlSerializer xmlSerializer = new XmlSerializer(toDeserialize);


// construct a StringReader class instance of the given xmlData parameter to be deserialized by the XmlSerializer class instance..
using (StringReader stringReader = new StringReader(xmlData))
{
// return the "new" object deserialized via the XmlSerializer class instance..
return xmlSerializer.Deserialize(stringReader);
}
}
}
}