it-swarm.dev

Serializovat objekt na řetězec

Mám následující metodu uložit objekt do souboru:

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

Přiznávám, že jsem to nezapisoval (konvertoval jsem ho pouze na metodu rozšíření, která měla parametr typu).

Teď to potřebuju, aby mi xml vrátil jako řetězec (místo abych ho uložil do souboru). Dívám se do ní, ale ještě jsem to nenapadlo.

Myslel jsem, že to může být pro někoho, kdo je obeznámen s těmito objekty, opravdu snadné. Pokud ne, nakonec to přijdu.

264
Vaccano

Použít StringWriter namísto souboru 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();
    }
}

Poznámka: je důležité použít toSerialize.GetType() namísto typeof(T) v konstruktoru XmlSerializer: pokud použijete první, kód pokrývá všechny možné podtřídy T (které jsou pro metodu platné), zatímco druhý z nich selže při předávání typu odvozeného z T. Zde je odkaz s nějakým příkladem kódu, který motivuje toto prohlášení, s XmlSerializer házením Exception, když je typeof(T) použito, protože předáte instanci odvozeného typu metodě, která volá SerializeObject, který je definované v základní třídě odvozeného typu: http://ideone.com/1Z5J1 .

Ideone také používá Mono ke spuštění kódu; Skutečný Exception byste dostali pomocí runtime Microsoft .NET má jiný Message než ten, který je zobrazen na Ideone, ale to selže stejně.

463
dtb

Vím, že to není opravdu odpověď na otázku, ale na základě počtu hlasů pro otázku a přijaté odpovědi mám podezření, že lidé ve skutečnosti používají kód k serializaci objektu na řetězec.

Použití serializace XML přidává zbytečný textový odpad do výstupu.

Pro následující třídu

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

generuje 

<?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>

Lepším řešením je použití serializace JSON (jeden z nejlepších je Json.NET ). Pro serializaci objektu:

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

Opuštění objektu:

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

Řetěz serializovaného JSON by vypadal takto:

{"UserId":0}
66
xhafan

Serializovat a deserializovat:

    public static T Deserialize<T>(this string toDeserialize)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        using(StringReader textReader = new StringReader(toDeserialize))
        {      
            return (T)xmlSerializer.Deserialize(textReader);
        }
    }

    public static string Serialize<T>(this T toSerialize)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        using(StringWriter textWriter = new StringWriter())
        {
            xmlSerializer.Serialize(textWriter, toSerialize);
            return textWriter.ToString();
        }
    }
49
ADM-IT

Kód Bezpečnostní upozornění

Co se týče přijaté odpovědi , je důležité použít toSerialize.GetType() namísto typeof(T) v konstruktoru XmlSerializer: pokud použijete první, kód pokrývá všechny možné scénáře, zatímco druhý z nich někdy selže. 

Zde je odkaz s nějakým příkladem kódu, který motivuje toto prohlášení, s XmlSerializer házením Výjimky při použití typeof(T), protože předáváte instanci odvozeného typu metodě, která volá SerializeObject<T>(), která je definována v základní třídě odvozeného typu: http://ideone.com/1Z5J1 . Všimněte si, že Ideone používá Mono ke spuštění kódu: skutečná výjimka, kterou byste získali pomocí runtime Microsoft .NET, má jinou zprávu než ten, který je zobrazen na Ideone, ale nezdaří to samé. 

Z důvodu úplnosti zde zveřejním celý ukázkový kód pro budoucí použití, pouze v případě, že Ideone (kde jsem kód poslal) nebude v budoucnu k dispozici:

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

Můj 2p ...

        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());
                }
            }
        }
10
oPless
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();
            }
        }
4
teapeng

Nemohl jsem použít metodu JSONConvert, kterou navrhl xhafan

V .Net 4.5 i po přidání odkazu "System.Web.Extensions" shromáždění jsem stále nemohl přistupovat k aplikaci JSONConvert.

Jakmile však přidáte odkaz, můžete vytisknout stejný řetězec pomocí:

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

Cítil jsem se, jako bych potřeboval sdílet tento manipulovaný kód s přijatou odpovědí - protože nemám žádnou pověst, nemohu se k tomu vyjádřit.

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

0