Programing

객체를 문자열로 직렬화

lottogame 2020. 3. 20. 08:11
반응형

객체를 문자열로 직렬화


Object를 파일에 저장하는 다음 방법이 있습니다.

// 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을 파일로 저장하지 않고 문자열로 다시 제공해야합니다. 나는 그것을 조사하고 있지만 아직 이해하지 못했습니다.

나는이 객체에 익숙한 사람에게는 이것이 정말 쉽다고 생각했습니다. 그렇지 않다면 결국 알아낼 것입니다.


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를 던지는 Exception경우 typeof(T): 사용하면 파생 형의 기본 클래스에 정의되어 SerializeObject를 호출하는 방법에 파생 된 유형의 인스턴스를 전달하기 때문에, HTTP는 : // ideone .com / 1Z5J1 .

또한 Ideone은 Mono를 사용하여 코드를 실행합니다. 실제로 ExceptionMicrosoft .NET 런타임을 사용하면 MessageIdeone에 표시된 것과 다르지만 동일하게 실패합니다.


나는 이것이 실제로 질문에 대한 답변이 아니라는 것을 알고 있지만 질문에 대한 투표 수와 허용 된 답변을 바탕으로 사람들이 실제로 코드를 사용하여 객체를 문자열로 직렬화한다고 생각합니다.

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}

직렬화 및 역 직렬화 :

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

코드 안전 정보

에 대해서는 허용 대답 , 그것을 사용하는 것이 중요합니다 toSerialize.GetType()대신 typeof(T)XmlSerializer생성자 : 후자를 사용하는 동안, 코드는 가능한 모든 시나리오를 다루고 첫 번째를 사용하는 경우 종종 실패합니다.

다음은 파생 된 유형의 기본 클래스에 정의 된 호출하는 메소드에 파생 된 유형의 인스턴스를 전달하기 때문에 사용 된 XmlSerializer경우 Exception을 발생시키면서이 명령문을 동기 부여하는 예제 코드가있는 링크입니다 . http : // ideone .com / 1Z5J1 . Ideone은 Mono를 사용하여 코드를 실행합니다. Microsoft .NET 런타임을 사용하는 실제 예외는 Ideone에 표시된 것과 다른 메시지를 갖지만 동일하게 실패합니다.typeof(T)SerializeObject<T>()

완벽을 기하기 위해 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();
    }
}

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

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

xhafan이 제안한 JSONConvert 메소드를 사용할 수 없습니다

.Net 4.5에서는 "System.Web.Extensions"어셈블리 참조를 추가 한 후에도 여전히 JSONConvert에 액세스 할 수 없었습니다.

그러나 참조를 추가하면 다음을 사용하여 동일한 문자열을 출력 할 수 있습니다.

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

이 조작 된 코드를 승인 된 답변에 공유해야 할 것 같은 느낌이 들었습니다. 평판이 없어서 댓글을 달 수 없습니다 ..

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


드문 경우지만 자체 문자열 직렬화를 구현할 수 있습니다.

그러나 당신이하고있는 일을 알지 못하면 아마도 나쁜 생각입니다. (예 : 배치 파일로 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;
}

[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

[씨#]

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

참고 URL : https://stackoverflow.com/questions/2434534/serialize-an-object-to-string

반응형