Saltar al contenido

Serializar un objeto como UTF-8 XML en .NET

Sé libre de compartir nuestro espacio y códigos con otro, necesitamos tu ayuda para aumentar nuestra comunidad.

Solución:

No, puedes usar un StringWriter para deshacerse del intermedio MemoryStream. Sin embargo, para forzarlo en XML necesita usar un StringWriter que anula el Encoding propiedad:

public class Utf8StringWriter : StringWriter

    public override Encoding Encoding => Encoding.UTF8;

O si aún no está usando C# 6:

public class Utf8StringWriter : StringWriter

    public override Encoding Encoding  get  return Encoding.UTF8;  

Entonces:

var serializer = new XmlSerializer(typeof(SomeSerializableObject));
string utf8;
using (StringWriter writer = new Utf8StringWriter())

    serializer.Serialize(writer, entry);
    utf8 = writer.ToString();

Obviamente puedes hacer Utf8StringWriter en una clase más general que acepta cualquier codificación en su constructor, pero en mi experiencia, UTF-8 es, con mucho, la codificación “personalizada” más comúnmente requerida para un StringWriter 🙂

Ahora, como dice Jon Hanna, esto seguirá siendo UTF-16 internamente, pero presumiblemente lo pasarás a otra cosa en algún momento, para convertirlo en datos binarios… en ese punto que puede utilizar el anterior stringconviértalo en bytes UTF-8 y todo irá bien, porque la declaración XML especificará “utf-8” como codificación.

EDITAR: un ejemplo breve pero completo para mostrar este funcionamiento:

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

public class Test
    
    public int X  get; set; 

    static void Main()
    
        Test t = new Test();
        var serializer = new XmlSerializer(typeof(Test));
        string utf8;
        using (StringWriter writer = new Utf8StringWriter())
        
            serializer.Serialize(writer, t);
            utf8 = writer.ToString();
        
        Console.WriteLine(utf8);
    


    public class Utf8StringWriter : StringWriter
    
        public override Encoding Encoding => Encoding.UTF8;
    

Resultado:



  0

Tenga en cuenta la codificación declarada de “utf-8”, que es lo que queríamos, creo.

Su código no obtiene el UTF-8 en la memoria cuando lo vuelve a leer en un string nuevamente, ya no está en UTF-8, sino en UTF-16 (aunque idealmente es mejor considerar las cadenas en un nivel más alto que cualquier codificación, excepto cuando se vea obligado a hacerlo).

Para obtener los octetos UTF-8 reales, podría usar:

var serializer = new XmlSerializer(typeof(SomeSerializableObject));

var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8);

serializer.Serialize(streamWriter, entry);

byte[] utf8EncodedXml = memoryStream.ToArray();

He dejado fuera la misma disposición que has dejado tú. Estoy ligeramente a favor de lo siguiente (con la eliminación normal dejada):

var serializer = new XmlSerializer(typeof(SomeSerializableObject));
using(var memStm = new MemoryStream())
using(var  xw = XmlWriter.Create(memStm))

  serializer.Serialize(xw, entry);
  var utf8 = memStm.ToArray();

Lo cual tiene la misma cantidad de complejidad, pero muestra que en cada etapa hay una opción razonable para hacer otra cosa, la más apremiante de las cuales es serializar en algún lugar que no sea la memoria, como un archivo, TCP/IP. flujo, base de datos, etc. En general, no es realmente tan detallado.

Muy buena respuesta usando herencia, solo recuerda anular el inicializador

public class Utf8StringWriter : StringWriter

    public Utf8StringWriter(StringBuilder sb) : base (sb)
    
    
    public override Encoding Encoding  get  return Encoding.UTF8;  

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *