I am trying to serialize two List objections to SQL Server.
This is my serialization code:
public static string SerializeToXml<T>(this T value)
{
var writer = new StringWriter(CultureInfo.InvariantCulture);
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(writer, value);
return writer.ToString();
}
When the following property is serialized and then saved, everything looks fine:
this.IPHostList = liveHostIps.SerializeToXml<List<string>>();
But when I try this with a custom class, I do not get any data.
this.MyClassList = MyClassContainer.SerializeTpXml<List<MyClass>>();
As an example of what I see in my database for the failed item:
<ArrayOfMyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
An example of what I see from the successful item:
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>192.168.1.4</string>
<string>192.168.1.5</string>
</ArrayOfString>
I tried serializing to XML for the benefit of viewing the data in the database, but if needed I can just convert to base64.
Any thoughts on why my custom class is not being saved? My custom class is:
[Serializable]
public class MyClass
{
public bool prop1{get;set;}
public Nullable<System.Guid> prop2 {get;set;}
public string prop3 {get;set;}
}
Note that I get no code errors - just that my xml array stored in the database is nonexistent.
I reproduced your code and ran it through a unit test but it seems to serialize properly. Here's my entire code. Maybe looking through this will help. Put a break on Assert.IsNotNull and you'll see that the serialization appears to be properly handled.
using System;
[Serializable]
public class MyCustomClass
{
public bool prop1 { get; set; }
public Nullable<Guid> prop2 { get; set; }
public string prop3 { get; set; }
}
using System.Globalization;
using System.IO;
using System.Xml.Serialization;
public static class MySerializer
{
public static string SerializeToXml<T>(this T value)
{
var writer = new StringWriter(CultureInfo.InvariantCulture);
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(writer, value);
return writer.ToString();
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var myCustomClasses = new List<MyCustomClass>();
myCustomClasses.Add(new MyCustomClass { prop1 = true, prop2 = Guid.NewGuid(), prop3 = "Testing" });
myCustomClasses.Add(new MyCustomClass { prop1 = true, prop2 = null, prop3 = "Testing2" });
var serialized = MySerializer.SerializeToXml(myCustomClasses);
Assert.IsNotNull(serialized);
}
}
Related
I have serialized a complex object( containing abstract classes, read only properties) using Newtonsoft.Jsonconverter SerializeObject successfully.
While trying to Deserialize the same using DeserializeObject method, it throws following error
- An item with this key has already been added.
On further investigation I found out that there might be some properties in the object with same name. But I couldn't find any property name being repeated in json file being de-serialized.
Version of NewtonSoft Json : 8.0.3
Hi I was trying to replicate your error but actually what I got was a successful result. this is the test I did :
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
var child = new Child();
var serializesObject = JsonConvert.SerializeObject(child);
var deserializedObject = JsonConvert.DeserializeObject(serializesObject, typeof(Child));
}
}
public abstract class Abstract
{
public int Prop1 { get; set; }
public readonly string Prop2;
public List<string> Prop3 { get; set; }
public int[] Prop4 { get; set; }
public abstract void Hey();
public Abstract()
{
Prop1 = 1;
Prop2 = "2";
Prop3 = new List<string>();
Prop4 = new int[4];
}
}
public class Child : Abstract
{
public readonly string Prop5;
public Child()
{
Prop5 = "5";
}
public override void Hey()
{
throw new NotImplementedException();
}
}
}
I hope that this code can help you to get to the expected result you want.
Cheers,
I don't know if the topic is correct, if not please correct. So far i am not sure what to search for my problem so maybe the question has already been answered before.
Currently i have the following class (as example):
[Serializable]
public class Sample
{
public string Something { get; set; }
public List<Parameter> Parameters { get; set; }
}
[Serializable]
public class Parameter
{
public string Name { get; set; }
public string Value { get; set; }
}
This structure i have to serialize to the following XML:
<Sample>
<Something>1234512345112345</Something>
<Parameters>
<Name>Value</Name>
<Name>Value</Name>
</Parameters>
</Sample>
So the XML should contain the property value of the attribute "Name" as XML-Element Name.
Update 20.05.2015
I have the following XML content:
<?xml version="1.0" encoding="utf-16" ?>
<ProcessData>
<ID>123456</ID>
<IDYTPE>BASEPLATE</IDYTPE>
<State>FAIL</State>
<Recipe>654321</Recipe>
<ProcessDataParameter>
<test_0>0</test_0>
<test_1>12,34</test_1>
<test_2>24,68</test_2>
<test_3>37,02</test_3>
<test_4>49,36</test_4>
<test_5>61,7</test_5>
</ProcessDataParameter>
</ProcessData>
When i try to use the following code to deserialize:
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement("ProcessData");
this.Id = reader.ReadElementString("ID");
this.IdType = reader.ReadElementString("IDYTPE");
this.State = reader.ReadElementString("State");
this.Recipe = reader.ReadElementString("Recipe");
reader.ReadStartElement("ProcessDataParameter");
this.ProcessDataParameter = new List<ProcessDataParameter>();
var subTree = reader.ReadSubtree();
while (subTree.Read())
{
if (subTree.NodeType == XmlNodeType.Text)
{
var nm = subTree.LocalName;
//Parameters.Add(new Parameter { Name = nm, Value = subTree.Value });
}
}
reader.ReadEndElement();
}
Everything gets read out fine expect the process data parameters.
It seems like the subTree.Read() just reades the element out of the XML content instead of all elements contained in the .
In the while loop the reader goes through the following values (debuged)
test_0 (start tag)
0 (value between the tag)
test_0 (end tag
and then out of the while.
Seems like the reader sees the as an subtree.
Further only the 0 - value gets recognized as XmlNodeType.Text
You could implement IXmlSerializable and create your own custom serialization behaviour for your Sample class. So in your case something like this should work
[Serializable]
public class Sample : IXmlSerializable
{
public string Something { get; set; }
public List<Parameter> Parameters { get; set; }
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
XmlDocument doc = new XmlDocument();
doc.Load(reader);
Something = doc.SelectSingleNode(#"/Sample/Something").FirstChild.Value;
var parameters = doc.SelectSingleNode(#"/Sample/Parameters");
if (parameters.HasChildNodes)
{
Parameters = new List<Parameter>();
foreach (XmlElement childNode in parameters.ChildNodes)
{
Parameters.Add(new Parameter {Name = childNode.LocalName, Value = childNode.FirstChild.Value});
}
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteElementString("Something", this.Something);
writer.WriteStartElement("Parameters");
foreach (var parameter in Parameters)
{
writer.WriteElementString(parameter.Name, parameter.Value);
}
writer.WriteEndElement();
}
}
Updated to include ReadXml implementation for deserialization
I'm not quite sure if the ReadXml is complete as I can't test this now, you might have to tweak it a bit for the Parameters
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
Sample sample = new Sample(){
Something = "1234512345112345",
Parameters = new List<Parameter>(){
new Parameter(){
Name = new List<string>(){"Value", "Value"}
}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(Sample));
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, sample);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer xs = new XmlSerializer(typeof(Sample));
XmlTextReader reader = new XmlTextReader(FILENAME);
Sample newSample = (Sample)xs.Deserialize(reader);
}
}
[XmlRoot("Sample")]
public class Sample
{
[XmlElement("Something")]
public string Something { get; set; }
[XmlElement("Parameters")]
public List<Parameter> Parameters { get; set; }
}
[XmlRoot("Parameters")]
public class Parameter
{
[XmlElement("Name")]
public List<string> Name { get; set; }
}
}
I want some Generic way to convert objects to xml nodes :
if i have some xml nodes like this:
<BusinessObject xmlns="http://xmlns.oracle.com/bpm/bpmobject/Data/BusinessObject"><?xml version="1.0" encoding="utf-16"?>
<BusinessObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<attribute1>sss</attribute1>
<attribute2>sss</attribute2>
</BusinessObject></BusinessObject>
I convert it to Json like that
{
"-xmlns": "http://xmlns.oracle.com/bpm/bpmobject/Data/BusinessObject",
"#text": "<?xml version=\"1.0\" encoding=\"utf-16\"?>
<BusinessObject xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
<attribute1>sss</attribute1>
<attribute2>sss</attribute2>
</BusinessObject>"
}
Then to c# class:
public class Rootobject
{
public string xmlns { get; set; }
public string text { get; set; }
}
Now how to reverse it to xml nodes again after setting its value ? I want a general solution not for this example
XML serialization is what you are looking for
public class Rootobject
{
public string xmlns { get; set; }
public string text { get; set; }
}
public static void Main(string[] args)
{
Rootobject details = new Rootobject();
details.xmlns = "myNamespace";
details.text = "Value";
Serialize(details);
}
static public void Serialize(Rootobject details)
{
XmlSerializer serializer = new XmlSerializer(typeof(Rootobject));
using (TextWriter writer = new StreamWriter(#"C:\Xml.xml"))
{
serializer.Serialize(writer, details);
}
}
You can use XML Serialization for converting a Class to XML, and viceversa.
For reference, read C# Tutorial - XML Serialization.
You can also refer to XML Schema Definition Tool
Example:
[DataContract]
public class MyClass1 {
[DataMember]
public string name;
[DataMember]
public int age;
}
Serialize / Deserialize
MyClass1 obj = new MyClass1();
DataContractSerializer dcs = new DataContractSerializer(typeof(MyClass1));
using (Stream stream = new FileStream(#"C:\tmp\file.xml", FileMode.Create, FileAccess.Write))
{
using (XmlDictionaryWriter writer =
XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8))
{
writer.WriteStartDocument();
dcs.WriteObject(writer, obj);
}
}
I think you need to apply the Serializable attribute to your class to be able to serialize it. This makes sure that your class does not use some none serializable attributes.
[Serializable]
public class Rootobject
{
public string xmlns { get; set; }
public string text { get; set; }
}
This is my first question on Stack Overflow. Apologies in advance if I don't do things quite right while I'm learning how things work here.
Here is my code :
public void TestSerialize()
{
ShoppingBag _shoppingBag = new ShoppingBag();
Fruits _fruits = new Fruits();
_fruits.testAttribute = "foo";
Fruit[] fruit = new Fruit[2];
fruit[0] = new Fruit("pineapple");
fruit[1]= new Fruit("kiwi");
_fruits.AddRange(fruit);
_shoppingBag.Items = _fruits;
Serialize<ShoppingBag>(_shoppingBag, #"C:\temp\shopping.xml");
}
public static void Serialize<T>(T objectToSerialize, string filePath) where T : class
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StreamWriter writer = new StreamWriter(filePath))
{
serializer.Serialize(writer, objectToSerialize);
}
}
[Serializable]
public class ShoppingBag
{
private Fruits _items;
public Fruits Items
{
get { return _items; }
set {_items = value; }
}
}
public class Fruits : List<Fruit>
{
public string testAttribute { get; set; }
}
[Serializable]
public class Fruit
{
public Fruit() { }
public Fruit(string value)
{
Name = value;
}
[XmlAttribute("name")]
public string Name { get; set; }
}
It produces this XML :
<?xml version="1.0" encoding="utf-8" ?>
<ShoppingBag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Items>
<Fruit name="pineapple" />
<Fruit name="kiwi" />
</Items>
</ShoppingBag>
I don't understand why I am not getting <Items testAttribute="foo">
Please can anyone tell me what I need to add to my code so that the Serializer will write this attribute out?
Thanks,
You need an intermediary class there:
class Program
{
static void Main()
{
var shoppingBag = new ShoppingBag
{
Items = new ShoppingBagItems
{
Fruits = new List<Fruit>(new[] {
new Fruit { Name = "pineapple" },
new Fruit { Name = "kiwi" },
}),
TestAttribute = "foo"
}
};
var serializer = new XmlSerializer(typeof(ShoppingBag));
serializer.Serialize(Console.Out, shoppingBag);
}
}
public class ShoppingBag
{
public ShoppingBagItems Items { get; set; }
}
public class ShoppingBagItems
{
[XmlElement("Fruit")]
public List<Fruit> Fruits { get; set; }
[XmlAttribute("testAttribute")]
public string TestAttribute { get; set; }
}
public class Fruit
{
[XmlAttribute("name")]
public string Name { get; set; }
}
Also note that you don't need to decorate your classes with the [Serializable] attribute as it is used only for binary serialization. Another remark is that you don't need to derive from List<T>, simply use it as a property.
Unfortunately, when serializing a collection the XmlSerializer doesn't take into account the extra properties of that collection. It only considers the members that implement ICollection<T>. If you want to serialize extra attributes, you need to wrap the collection in another class that is not a collection itself.
is it possible to partially (de)/serialize an object from/into a string?
class Foo
{
Bar Bar{get;set;}
string XmlJunkAsString{get;set;}
}
so ultmately, we would want the string below to work...
<Foo><Bar></Bar><XmlJunkAsString><xml><that/><will/><not/><be/><parsed/></xml></XmlJunkAsString></Foo>
and ultimately we could find the contents of Foo.XmlJunkAsString to contain the string
<xml><that/><will/><not/><be/><parsed/></xml>
and vice-versa would occur where the xml above would be generated when this particular instance of Foo is serialized.
possible?
I was hoping that [XmlText] would work, but it seems to get escaped; you could implement IXmlSerializable, but that is very tricky. The following is ugly, but gives the right result (although you might get some xml whitespace differences)
using System;
using System.ComponentModel;
using System.Xml;
using System.Xml.Serialization;
public class Bar { }
public class Foo
{
public Bar Bar { get; set; }
[XmlIgnore]
public string XmlJunkAsString { get; set; }
[XmlElement("XmlJunkAsString"), Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public XmlElement XmlJunkAsStringSerialized
{
get
{
string xml = XmlJunkAsString;
if (string.IsNullOrEmpty(xml)) return null;
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
return doc.DocumentElement;
}
set
{
XmlJunkAsString = value == null ? null : value.OuterXml;
}
}
}
static class Program {
static void Main()
{
var obj = new Foo
{
Bar = new Bar(),
XmlJunkAsString = "<xml><that/><will/><not/><be/><parsed/></xml>"
};
var ser = new XmlSerializer(obj.GetType());
ser.Serialize(Console.Out, obj);
}
}