2011-02-15 11 views
54

Tengo las siguientes funciones: 2DataContractSerializer para serializar, pero no puede deserializar espalda

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

El primero parece serializar un objeto a una cadena XML bien. El XML parece válido, no hay etiquetas rotas, no hay espacios en blanco al principio o al final, etc. Ahora la segunda función no quiere deserializar mi cadena xml de vuelta al objeto. En la última línea me sale:

Se ha producido un error al deserializar objeto de tipo [MI TIPO DE OBJETO AQUÍ]. Los datos en el nivel raíz no son válidos. Línea 1, posición 1.

¿Qué estoy haciendo mal? Traté de volver a escribir la función Deserializar varias veces, y siempre parece ser el mismo tipo de error. ¡Gracias!

Ah, y así es como llamo a la 2 funciones:

SomeObject so = new SomeObject(); 
string temp = SerializationManager.Serialize(so); 
so = (SomeObject)SerializationManager.Deserialize(temp, typeof(SomeObject)); 

Respuesta

121

Así es como yo siempre lo he hecho:

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

Para Deserialize, podría ser más eficiente reemplazar GetBytes/Write con "using (StreamWriter writer = new StreamWriter (transmisión, codificación) {writer.Write (xml); ...} "para evitar el búfer adicional [] buffer – crokusek

+1

Esto es increíble, y aún así increíblemente útil. Lo más importante, esto es correcto. – Feign

+0

He usado estos métodos también, pero tengo un pequeño problema cuando serialize-deserialize clases derivadas de una clase base. Tuve que modificar el método serialize solo un poco ([link] (https://stackoverflow.com/a/45443874/3785903)) para proporcionar el tipo de clase base. –

33

que terminé haciendo lo siguiente y se trabajos.

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

Parece que el problema principal era en la función Serialize al llamar stream.GetBuffer(). Llamar a stream.ToArray() parece funcionar.

+1

+1 para su solución – Divi

+1

GetBuffer() falla, porque el búfer de MemoryStream se asigna en trozos de 256 bytes y todos los bytes de todos los trozos, incluso los bytes cero no utilizados después de la terminación '\ 0' de la cadena son devueltos por GetBuffer(). cadena correctamente tiene un montón de ceros. – Doomjunky

-2

Esta mejor para XML Deserialize

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

    } 
+0

Puede proporcionar alguna explicación para su sugerencia. Consulte [Cómo responder] (http://stackoverflow.com/questions/how-to-answer). –

31

Otra solución es:

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

Una observación: a veces sucede que xml crudo contiene por ejemplo:

<?xml version="1.0" encoding="utf-16"?>

luego de Por supuesto, no puede usar la codificación UTF8 utilizada en otros ejemplos.

+4

+1 para tipos fuertes – Kaido

+5

+1 para uso de genéricos – PhilDulac

Cuestiones relacionadas