How to serialize List<object> - c#

I am writing common functions to serialize the given object and List<object> as follows
public string SerializeObject(Object pObject)// for given object
{
try
{
String XmlizedString = null;
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(pObject));
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
xs.Serialize(xmlTextWriter, pObject);
memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
return XmlizedString;
}
catch (Exception e) { System.Console.WriteLine(e); return null; }
}
public string SerializeObject(List<Object> pObject)// for given List<object>
{
try
{
String XmlizedString = null;
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(pObject));
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
xs.Serialize(xmlTextWriter, pObject);
memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
return XmlizedString;
}
catch (Exception e) { System.Console.WriteLine(e); return null; }
}
first one is working fine. If I pass any type, it is successfully returning xml string.
CORRECTION: Compilation error has occurred for second one (Error: cannot convert from List<MyType> to List<object>.
I rewrite the second one as follows which solves my problem. Now it is serializing the given List<generic types>.
private string SerializeObject<T>(T source)
{
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(T));
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
xs.Serialize(xmlTextWriter, source);
memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
string XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
return XmlizedString;
}

https://weblogs.asp.net/rajbk/Contents/Item/Display/345
The relevant code from the article:
private static string SerializeObject<T>(T source)
{
var serializer = new XmlSerializer(typeof(T));
using (var sw = new System.IO.StringWriter())
using (var writer = XmlWriter.Create(sw))
{
serializer.Serialize(writer, source);
return sw.ToString();
}
}

I have tried your two functions without much trouble. The only thing I changed was this line:
XmlSerializer xs = new XmlSerializer(typeof(pObject));
to this:
XmlSerializer xs = new XmlSerializer(pObject.GetType());
typeof() requires an actual type whereas GetType() returns the type of the object.

Related

How to Convert Different Enities in a single XML string

I have Converted a the Different entities in a List and now I have a master list containing the many list of different models.
public static string xmlSerialize(List<Object> o)
{
XmlDocument xmlOut = new XmlDocument();
foreach(var i in o)
{
using (MemoryStream xmlStream = new MemoryStream())
{
//MemoryStream myMemStr = new MemoryStream();
XmlSerializer xmlSerializer = new XmlSerializer(i.GetType());
xmlSerializer.Serialize(xmlStream, i);
xmlStream.Position = 0;
xmlOut.Load(xmlStream);
}
}
return xmlOut.InnerXml;
}
The above method converts the multiple List into a XML. But this code Overwrites the previous XML string in every loop run.
Is There any solution to get the single XML for every entity.
IMHO - the simplest solution here is to load xml into temporary XmlDocument and then perform Import
Idea is the following
public static string xmlSerialize(List<Object> o)
{
XmlDocument xmlOut = new XmlDocument();
foreach(var i in o)
{
var tmpDoc = new XmlDocument();
using (MemoryStream xmlStream = new MemoryStream())
{
//MemoryStream myMemStr = new MemoryStream();
XmlSerializer xmlSerializer = new XmlSerializer(i.GetType());
xmlSerializer.Serialize(xmlStream, i);
xmlStream.Position = 0;
tmpDoc.Load(xmlStream);
}
var newNode = xmlOut.ImportNode(tmpDoc.DocumentElement.LastChild, true);
xmlOut.DocumentElement.AppendChild(newNode);
}
return xmlOut.InnerXml;
}

Round trip XML serializing with .Net DataContractSerializer fails

I seem to be getting some junk at the head of my serialized XML string. I have a simple extension method
public static string ToXML(this object This)
{
DataContractSerializer ser = new DataContractSerializer(This.GetType());
var settings = new XmlWriterSettings { Indent = true };
using (MemoryStream ms = new MemoryStream())
using (var w = XmlWriter.Create(ms, settings))
{
ser.WriteObject(w, This);
w.Flush();
return UTF8Encoding.Default.GetString(ms.ToArray());
}
}
and when I apply it to my object I get the string
<?xml version="1.0" encoding="utf-8"?>
<RootModelType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WeinCad.Data">
<MoineauPump xmlns:d2p1="http://schemas.datacontract.org/2004/07/Weingartner.Numerics">
<d2p1:Rotor>
<d2p1:Equidistance>0.0025</d2p1:Equidistance>
<d2p1:Lobes>2</d2p1:Lobes>
<d2p1:MajorRadius>0.04</d2p1:MajorRadius>
<d2p1:MinorRadius>0.03</d2p1:MinorRadius>
</d2p1:Rotor>
</MoineauPump>
</RootModelType>
Note the junk at the beginning. When I try to deserialize this
I get an error. If I copy paste the XML into my source minus
the junk prefix I can deserialize it. What is the junk text
and how can I remove it or handle it?
Note my deserialization code is
public static RootModelType Load(Stream data)
{
DataContractSerializer ser = new DataContractSerializer(typeof(RootModelType));
return (RootModelType)ser.ReadObject(data);
}
public static RootModelType Load(string data)
{
using(var stream = new MemoryStream(Encoding.UTF8.GetBytes(data))){
return Load(stream);
}
}
This fix seems to work
public static string ToXML(this object obj)
{
var settings = new XmlWriterSettings { Indent = true };
using (MemoryStream memoryStream = new MemoryStream())
using (StreamReader reader = new StreamReader(memoryStream))
using(XmlWriter writer = XmlWriter.Create(memoryStream, settings))
{
DataContractSerializer serializer =
new DataContractSerializer(obj.GetType());
serializer.WriteObject(writer, obj);
writer.Flush();
memoryStream.Position = 0;
return reader.ReadToEnd();
}
}

DataContractSerializer - how can I output the xml to a string (as opposed to a file)

I had a quick question regarding the datacontractserializer. Maybe it's more of a stream question. I found a piece of code that writes the xml to a filestream. I basically don't want the file and just need the string output.
public static string DataContractSerializeObject<T>(T objectToSerialize)
{
var fs = new FileStream("test.xml", FileMode.OpenOrCreate);
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(fs, objectToSerialize);
fs.Close();
return fs.ToString();
}
fs.ToString() is obviously not what I'm looking for. What stream or writer etc, can I use just to return the proper string and not create a file? I did look at the XML the filestream created and it's exactly what I'm looking for. The XmlSerializer wrote the XML a bit strange and I prefer the output of the DataContractSerializer in this case. Can anyone point me in the right direction?
Something like this - put your output into a MemoryStream and then read that back in:
public static string DataContractSerializeObject<T>(T objectToSerialize)
{
using(MemoryStream memStm = new MemoryStream())
{
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(memStm, objectToSerialize);
memStm.Seek(0, SeekOrigin.Begin);
using(var streamReader = new StreamReader(memStm))
{
string result = streamReader.ReadToEnd();
return result;
}
}
}
Thanks to #xr280xr for pointing out my forgotten StringWriter disposal in the first draft.
/// <summary>
/// Converts this instance to XML.
/// </summary>
/// <returns>XML representing this instance.</returns>
public string ToXml()
{
var serializer = new DataContractSerializer(this.GetType());
using (var output = new StringWriter())
using (var writer = new XmlTextWriter(output) { Formatting = Formatting.Indented })
{
serializer.WriteObject(writer, this);
return output.GetStringBuilder().ToString();
}
}
And even easier:
var serializer = new DataContractSerializer(typeof(T));
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb))
{
serializer.WriteObject(writer, objectToSerialize);
writer.Flush();
return sb.ToString();
}
I suggest combining the methods given by Pat and marc_s:
public static string DataContractSerializeObject<T>(T objectToSerialize)
{
using (var output = new StringWriter())
using (var writer = new XmlTextWriter(output) {Formatting = Formatting.Indented})
{
new DataContractSerializer(typeof (T)).WriteObject(writer, objectToSerialize);
return output.GetStringBuilder().ToString();
}
}
A variant of #root's answer:
var serializer = new DataContractSerializer(typeof(T));
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb))
{
serializer.WriteObject(writer, objectToSerialize);
}
return sb.ToString();

How to keep XmlSerializer from killing NewLines in Strings?

Suppose I have a simple Class with just one Member a String.
public class Abc
{
private String text;
public String Text
{
get { return this.text; }
set { this.text = value; }
}
}
Now when I serialize and then deserialize it with the questionable XmlSerializer any text containing newlines ('\r\n' or Environment.NewLine) are transformed to '\n'.
How do I keep the newlines?
It is not the XmlSerializer but the XmlWriter which is removing your CR. To retain it we must have the writer convert CR to its character entity 
.
XmlWriterSettings ws = new XmlWriterSettings();
ws.NewLineHandling = NewLineHandling.Entitize;
XmlSerializer ser = new XmlSerializer( typeof( Abc ) );
using (XmlWriter wr = XmlWriter.Create( "abc.xml", ws )) {
ser.Serialize( wr, s );
}
This is exactly the same with DataContractSerializer:
var ser = new DataContractSerializer( typeof( Abc ) );
using (XmlWriter wr = XmlWriter.Create( "abc.xml", ws )) {
ser.Serialize( wr, s );
}
Why do we need to do this?
This is because compliant XML parsers must, before parsing, translate CRLF and any CR not followed by a LF to a single LF. This behavior is defined in the End-of-Line handling section of the XML 1.0 specification.
As this happens before parsing, you need to encode CR as its character entity if you want the CR to exist in the document.
public class SerializeAny<TF> where TF : new()
{
public static TF Deserialize(string serializedData)
{
try
{
var xmlSerializer = new XmlSerializer(typeof(TF));
TF collection;
using (var xmlReader = new XmlTextReader(serializedData, XmlNodeType.Document, null))
{
collection = (TF)xmlSerializer.Deserialize(xmlReader);
}
return collection;
}
catch (Exception)
{
}
return new TF();
}
public static TF DeserializeZip(string path)
{
try
{
var bytes = File.ReadAllBytes(path);
string serializedData = Unzip(bytes);
TF collection = Deserialize(serializedData);
return collection;
}
catch (Exception)
{
}
return new TF();
}
public static string Serialize(TF options)
{
var xml = "";
try
{
var xmlSerializer = new XmlSerializer(typeof(TF));
using (var stringWriter = new StringWriter())
{
xmlSerializer.Serialize(stringWriter, options);
xml = stringWriter.ToString();
}
}
catch (Exception ex)
{
return ex.Message;
}
return xml;
}
public static string SerializeZip(TF options, string path)
{
var xml = "";
try
{
xml = Serialize(options);
var zip = Zip(xml);
File.WriteAllBytes(path, zip);
}
catch (Exception ex)
{
return ex.Message;
}
return xml;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
internal static String SerializeObject<T>(T obj, Encoding enc)
{
using (var ms = new MemoryStream())
{
var xmlWriterSettings = new System.Xml.XmlWriterSettings()
{
// If set to true XmlWriter would close MemoryStream automatically and using would then do double dispose
// Code analysis does not understand that. That's why there is a suppress message.
CloseOutput = false,
Encoding = enc,
OmitXmlDeclaration = false,
Indent = true
};
using (var xw = XmlWriter.Create(ms, xmlWriterSettings))
{
var s = new XmlSerializer(typeof(T));
s.Serialize(xw, obj);
}
return enc.GetString(ms.ToArray());
}
}
private static void CopyTo(Stream src, Stream dest)
{
byte[] bytes = new byte[4096];
int cnt;
while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0)
{
dest.Write(bytes, 0, cnt);
}
}
private static byte[] Zip(string str)
{
var bytes = Encoding.UTF8.GetBytes(str);
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream())
{
using (var gs = new GZipStream(mso, CompressionMode.Compress))
{
//msi.CopyTo(gs);
CopyTo(msi, gs);
}
return mso.ToArray();
}
}
private static string Unzip(byte[] bytes)
{
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream())
{
using (var gs = new GZipStream(msi, CompressionMode.Decompress))
{
CopyTo(gs, mso);
}
return Encoding.UTF8.GetString(mso.ToArray());
}
}
}
public class BinarySerialize<T> where T : new()
{
public static string Serialize(T options, string path)
{
var xml = "";
try
{
File.Delete(path);
}
catch (Exception)
{
}
try
{
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
var bf = new BinaryFormatter();
bf.Serialize(fs, options);
}
}
catch (Exception ex)
{
return ex.Message;
}
return xml;
}
public static T Deserialize(string path)
{
T filteroptions;
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var bf = new BinaryFormatter();
filteroptions = (T)bf.Deserialize(fs);
}
return filteroptions;
}
}
Use this code:
public static FilterOptions Deserialize(string serializedData)
{
try
{
var xmlSerializer = new XmlSerializer(typeof(FilterOptions));
var xmlReader = new XmlTextReader(serializedData,XmlNodeType.Document,null);
var collection = (FilterOptions)xmlSerializer.Deserialize(xmlReader);
return collection;
}
catch (Exception)
{
}
return new FilterOptions();
}
Nice solution, Lachlan Roche!
The function below (in VB.NET) uses a StringWriter to return a String, rather than writing the result to a file using an XmlWriter.
''' <summary>
''' Exports the object data to an XML formatted string.
''' Maintains CR characters after deserialization.
''' The object must be serializable to work.
''' </summary>
Public Function ExportObjectXml(ByVal obj As Object) As String
If obj Is Nothing Then
Return String.Empty
End If
Dim serializer As New XmlSerializer(obj.GetType)
Dim settings As New XmlWriterSettings With {.NewLineHandling = NewLineHandling.Entitize}
Using output As New StringWriter
Using writer As XmlWriter = XmlWriter.Create(output, settings)
serializer.Serialize(writer, obj)
Return output.ToString
End Using
End Using
End Function

InvalidOperationException while SOAP serialization of complex type

I encountered a problem with SOAP serialization and it would be great to find an answer. Here's a very simplified example:
public void Test()
{
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb);
SoapReflectionImporter importer = new SoapReflectionImporter();
XmlTypeMapping map = importer.ImportTypeMapping(typeof(A));
XmlSerializer serializer = new XmlSerializer(map);
serializer.Serialize(writer, new A());
}
[Serializable]
public class A
{
public A()
{
BB = new B();
}
public int a;
public B BB;
}
[Serializable]
public class B
{
public int A1 { get; set; }
public int A2 { get; set; }
}
If I run method Test() then I get the following exception: System.InvalidOperationException: Token StartElement in state Epilog would result in an invalid XML document.
Would appreciate any help.
Use XmlWriter instead of StringWriter and do a writer.WriteStartElement("root");
This will work:
Stream s = new MemoryStream();
XmlWriter writer = new XmlTextWriter(s, Encoding.UTF8);
SoapReflectionImporter importer = new SoapReflectionImporter();
XmlTypeMapping map = importer.ImportTypeMapping(typeof(A));
XmlSerializer serializer = new XmlSerializer(map);
writer.WriteStartElement("root");
serializer.Serialize(writer, new A());
StreamReader sr = new StreamReader(s);
string data = sr.ReadToEnd();
Just a note,
The upper example will not work if the position of the stream is not set to the start of the stream. Like so:
Stream s = new MemoryStream();
XmlWriter writer = new XmlTextWriter(s, Encoding.UTF8);
SoapReflectionImporter importer = new SoapReflectionImporter();
XmlTypeMapping map = importer.ImportTypeMapping(typeof(A));
XmlSerializer serializer = new XmlSerializer(map);
writer.WriteStartElement("root");
serializer.Serialize(writer, new A());
s.Position = 0;
StreamReader sr = new StreamReader(s);
string data = sr.ReadToEnd();

Categories

Resources