我有以下2个功能:
public static string Serialize(object obj)
{
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
MemoryStream memoryStream = new MemoryStream();
serializer.WriteObject(memoryStream, obj);
return Encoding.UTF8.GetString(memoryStream.GetBuffer());
}
public static object Deserialize(string xml, Type toType)
{
MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
// memoryStream.Position = 0L;
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.UTF8, new XmlDictionaryReaderQuotas(), null);
DataContractSerializer dataContractSerializer = new DataContractSerializer(toType);
return dataContractSerializer.ReadObject(reader);
}
第一个似乎可以将对象序列化为 xml 字符串。 XML 显示有效,没有损坏的标签,开头或结尾没有空格等。现在第二个函数不想将我的 XML 字符串反序列化回对象。在最后一行我得到:
反序列化时出错 [此处是我的对象类型] 类型的对象。 根级别的数据无效。 1 号线,1 号位置。
我做错了什么?我尝试重写反序列化函数几次,但似乎总是出现同样的错误。
哦,这就是我调用这两个函数的方式:
SomeObject so = new SomeObject();
string temp = SerializationManager.Serialize(so);
so = (SomeObject)SerializationManager.Deserialize(temp, typeof(SomeObject));
我一直都是这么做的:
public static string Serialize(object obj) {
using(MemoryStream memoryStream = new MemoryStream())
using(StreamReader reader = new StreamReader(memoryStream)) {
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
serializer.WriteObject(memoryStream, obj);
memoryStream.Position = 0;
return reader.ReadToEnd();
}
}
public static object Deserialize(string xml, Type toType) {
using(Stream stream = new MemoryStream()) {
byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
stream.Write(data, 0, data.Length);
stream.Position = 0;
DataContractSerializer deserializer = new DataContractSerializer(toType);
return deserializer.ReadObject(stream);
}
}
其他解决方案是:
public static T Deserialize<T>(string rawXml)
{
using (XmlReader reader = XmlReader.Create(new StringReader(rawXml)))
{
DataContractSerializer formatter0 =
new DataContractSerializer(typeof(T));
return (T)formatter0.ReadObject(reader);
}
}
备注:有时原始 xml 会包含例如:
<?xml version="1.0" encoding="utf-16"?>
那么你当然不能使用其他示例中使用的UTF8编码..
我最终做了以下事情并且它有效。
public static string Serialize(object obj)
{
using (MemoryStream memoryStream = new MemoryStream())
{
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
serializer.WriteObject(memoryStream, obj);
return Encoding.UTF8.GetString(memoryStream.ToArray());
}
}
public static object Deserialize(string xml, Type toType)
{
using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.UTF8, new XmlDictionaryReaderQuotas(), null);
DataContractSerializer serializer = new DataContractSerializer(toType);
return serializer.ReadObject(reader);
}
}
看来主要问题是在调用stream.GetBuffer()时的Serialize函数中。调用stream.ToArray()似乎可以工作。
Serialize
/Deserialize
方法的稍微复杂的版本。我使用的是 MemoryStream
+StreamReader
,而不是 StringBuilder
+XmlWriter
组合,它允许控制 XML 输出的缩进 (XmlWriterSettings.Indent
):
public static string Serialize<T>(T value, bool indented = false)
{
StringBuilder stringBuilder = new();
XmlWriterSettings settings = new();
settings.Indent = indented;
DataContractSerializer serializer = new(typeof(T));
using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder, settings))
serializer.WriteObject(xmlWriter, value);
return stringBuilder.ToString();
}
public static T Deserialize<T>(string xml)
{
ArgumentNullException.ThrowIfNull(xml);
DataContractSerializer serializer = new(typeof(T));
using StringReader stringReader = new(xml);
using XmlReader xmlReader = XmlReader.Create(stringReader);
return (T)serializer.ReadObject(xmlReader);
}
使用示例:
string xml = Serialize(obj, indented: true);
MyClass obj = Deserialize<MyClass>(xml);
注意: 不要尝试通过将
using (XmlWriter
语句转换为
using
声明来改进 using
行,因为在读取 XmlWriter
之前必须关闭 StringBuilder
。
这最适合 XML 反序列化
public static object Deserialize(string xml, Type toType)
{
using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
System.IO.StreamReader str = new System.IO.StreamReader(memoryStream);
System.Xml.Serialization.XmlSerializer xSerializer = new System.Xml.Serialization.XmlSerializer(toType);
return xSerializer.Deserialize(str);
}
}