首页 文章

将对象序列化为字符串

提问于
浏览
260

我有以下方法将对象保存到文件:

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

我承认我没有写它(我只将其转换为带有类型参数的扩展方法) .

现在我需要它将xml作为字符串返回给我(而不是将其保存到文件中) . 我正在研究它,但我还没想到它 .

我认为对于熟悉这些对象的人来说这可能很容易 . 如果不是,我最终会弄明白 .

10 回答

  • 62

    使用StringWriter而不是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();
        }
    }
    

    注意,在XmlSerializer构造函数中使用 toSerialize.GetType() 而不是 typeof(T) 非常重要:如果使用第一个代码,则代码涵盖 T 的所有可能子类(对方法有效),而使用后者则在传递派生类型时会失败来自 T . 下面是一些激活此语句的示例代码的链接, XmlSerializer 在使用 typeof(T) 时抛出 Exception ,因为您将派生类型的实例传递给调用在派生类型的基类中定义的SerializeObject的方法:http://ideone.com/1Z5J1 .

    此外,Ideone使用Mono执行代码;使用Microsoft .NET运行时的实际 Exception 与Ideone上显示的实际 Message 不同,但它失败的方式相同 .

  • 36

    我知道这不是问题的答案,但根据问题的投票数和接受的答案,我怀疑人们实际上是在使用代码将对象序列化为字符串 .

    使用XML序列化会在输出中添加不必要的额外文本垃圾 .

    对于以下课程

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

    它会产生

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

    更好的解决方案是使用JSON序列化(最好的之一是Json.NET) . 要序列化对象:

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

    要反序列化对象:

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

    序列化的JSON字符串如下所示:

    {"UserId":0}
    
  • 10

    序列化和反序列化:

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

    代码安全说明

    关于accepted answer,重要的是在 XmlSerializer 构造函数中使用 toSerialize.GetType() 而不是 typeof(T) :如果使用第一个代码涵盖所有可能的场景,而使用后者则有时会失败 .

    下面是一个激活此语句的示例代码的链接, XmlSerializer 在使用 typeof(T) 时抛出异常,因为您将派生类型的实例传递给调用派生类型基类中定义的 SerializeObject<T>() 的方法:http://ideone.com/1Z5J1 . 请注意,Ideone使用Mono来执行代码:使用Microsoft .NET运行时获得的实际异常消息与Ideone上显示的消息不同,但它失败的方式相同 .

    为了完整起见,我在这里发布完整的代码示例以供将来参考,以防Ideone(我发布代码的地方)将来变得不可用:

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

    我的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());
                    }
                }
            }
    
  • 4
    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();
                }
            }
    
  • 0

    我无法使用xhafan建议的JSONConvert方法

    在.Net 4.5中,即使添加了“System.Web.Extensions”程序集引用,我仍然无法访问JSONConvert .

    但是,一旦添加引用,您就可以使用以下命令打印出相同的字符串:

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

    我觉得我需要将这个被操纵的代码分享到接受的答案 - 因为我没有声誉,我无法评论..

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

    在极少数情况下,您可能希望实现自己的String序列化 .

    但这可能是一个 bad 的想法,除非你知道你在做什么 . (例如,使用批处理文件序列化I / O)

    这样的东西可以解决问题(手动/批量编辑很容易),但要注意应该做更多的检查,比如该名称不包含换行符 .

    public string name {get;set;}
    public int age {get;set;}
    
    Person(string serializedPerson) 
    {
        string[] tmpArray = serializedPerson.Split('\n');
        if(tmpArray.Length>2 && tmpArray[0].Equals("#")){
            this.name=tmpArray[1];
            this.age=int.TryParse(tmpArray[2]);
        }else{
            throw new ArgumentException("Not a valid serialization of a person");
        }
    }
    
    public string SerializeToString()
    {
        return "#\n" +
               name + "\n" + 
               age;
    }
    
  • -1

    [VB]

    Public Function XmlSerializeObject(ByVal obj As Object) As String
    
        Dim xmlStr As String = String.Empty
    
        Dim settings As New XmlWriterSettings()
        settings.Indent = False
        settings.OmitXmlDeclaration = True
        settings.NewLineChars = String.Empty
        settings.NewLineHandling = NewLineHandling.None
    
        Using stringWriter As New StringWriter()
            Using xmlWriter__1 As XmlWriter = XmlWriter.Create(stringWriter, settings)
    
                Dim serializer As New XmlSerializer(obj.[GetType]())
                serializer.Serialize(xmlWriter__1, obj)
    
                xmlStr = stringWriter.ToString()
                xmlWriter__1.Close()
            End Using
    
            stringWriter.Close()
        End Using
    
        Return xmlStr.ToString
    End Function
    
    Public Function XmlDeserializeObject(ByVal data As [String], ByVal objType As Type) As Object
    
        Dim xmlSer As New System.Xml.Serialization.XmlSerializer(objType)
        Dim reader As TextReader = New StringReader(data)
    
        Dim obj As New Object
        obj = DirectCast(xmlSer.Deserialize(reader), Object)
        Return obj
    End Function
    

    [C#]

    public string XmlSerializeObject(object obj)
    {
        string xmlStr = String.Empty;
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = false;
        settings.OmitXmlDeclaration = true;
        settings.NewLineChars = String.Empty;
        settings.NewLineHandling = NewLineHandling.None;
    
        using (StringWriter stringWriter = new StringWriter())
        {
            using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, settings))
            {
                XmlSerializer serializer = new XmlSerializer( obj.GetType());
                serializer.Serialize(xmlWriter, obj);
                xmlStr = stringWriter.ToString();
                xmlWriter.Close();
            }
        }
        return xmlStr.ToString(); 
    }
    
    public object XmlDeserializeObject(string data, Type objType)
    {
        XmlSerializer xmlSer = new XmlSerializer(objType);
        StringReader reader = new StringReader(data);
    
        object obj = new object();
        obj = (object)(xmlSer.Deserialize(reader));
        return obj;
    }
    

相关问题