使用DataContractSerializer进行序列化,但无法反序列化回来

问题描述 投票:0回答:5

我有以下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));
c# c#-4.0 xml-serialization datacontractserializer
5个回答
146
投票

我一直都是这么做的:

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

43
投票

其他解决方案是:

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编码..


34
投票

我最终做了以下事情并且它有效。

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()似乎可以工作。


0
投票

这是 Ray Vernagus 的

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


-2
投票

这最适合 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);
        }

    }
© www.soinside.com 2019 - 2024. All rights reserved.