I have an xml document that I don't control that has an element with a custom datatype
<foo>
<time type="epoch_seconds">1295027809.26896</time>
</foo>
I would like to have a class that could automatically convert to Epoch seconds:
[Serializable]
public class Foo
{
public Foo()
{
}
public EpochTime Time { get; set; }
}
Is there a way to define an EpochTime
class so that the XML serializer knows to use it when finding XML with type="epoch_time"
? And if so, how do I set up the WriteXml
and ReadXml
to do it?
XML serialization is the process of converting an object's public properties and fields to a serial format (in this case, XML) for storage or transport. Deserialization re-creates the object in its original state from the XML output.
Deserialization is the process of reading an XML document and constructing an object that is strongly typed to the XML Schema (XSD) of the document. Before deserializing, an XmlSerializer must be constructed using the type of the object that is being deserialized.
Jackson annotations are useful in defining and controlling the process of serialization and deserialization across various formats such as XML, JSON, and YAML.
The normal way is to simply shim it with a property that behaves as you expect:
public class EpochTime {
public enum TimeType {
[XmlEnum("epoch_seconds")] Seconds
}
[XmlAttribute("type")] public TimeType Type {get;set;}
[XmlText] public string Text {get;set;}
[XmlIgnore] public DateTime Value {
get { /* your parse here */ }
set { /* your format here */ }
}
}
also, you would need:
[XmlElement("time")]
public EpochTime Time { get; set; }
Here's a complete example with your xml:
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
static class Program
{
static void Main()
{
Foo foo;
var ser = new XmlSerializer(typeof(Foo));
using (var reader = XmlReader.Create(new StringReader(@"<foo>
<time type=""epoch_seconds"">1295027809.26896</time>
</foo>")))
{
foo = (Foo)ser.Deserialize(reader);
}
}
}
public class EpochTime
{
public enum TimeType
{
[XmlEnum("epoch_seconds")]
Seconds
}
[XmlAttribute("type")]
public TimeType Type { get; set; }
[XmlText]
public string Text { get; set; }
private static readonly DateTime Epoch = new DateTime(1970, 1, 1);
[XmlIgnore] public DateTime Value
{
get
{
switch (Type)
{
case TimeType.Seconds:
return Epoch + TimeSpan.FromSeconds(double.Parse(Text));
default:
throw new NotSupportedException();
}
}
set {
switch (Type)
{
case TimeType.Seconds:
Text = (value - Epoch).TotalSeconds.ToString();
break;
default:
throw new NotSupportedException();
}
}
}
}
[XmlRoot("foo")]
public class Foo
{
public Foo()
{
}
[XmlElement("time")]
public EpochTime Time { get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With