Friday, 19 May 2017

Serialization 04 Data Contract

The forth entry about Serialization deals with Data Contracts, these contracts are leveraged by the windows communication foundation for serialization and deserialization. However the Data Contract can be used independently from WCF.

Now to use data contracts you'll have to add a reference to "System.Runtime.Serialization".
The class to be serialized needs to be marked with a [DataContract] attribute
Every property to be serialized needs to be marked with a [DataMember] attribute
Any superclasses need to be identified with the [KnownType] attribute

[DataContract]
[KnownType(typeof(Employee))]
public class Person
{
    [DataMember]
    public string FirstName { get; private set; }

    [DataMember]
    string LastName { get; set; }

    public Person(string FirstName, string LastName)
    {
        this.FirstName = FirstName;
        this.LastName = LastName;
    }

    public string FullName { get { return $"{FirstName} {LastName}"; } }
}

[DataContract]
class Employee : Person
{
    static int _runningId;
    [DataMember]
    public int Id { get; private set; } = _runningId++;
    public Employee(string FirstName, string LastName) : base(FirstName, LastName) { }

}

Now serializing using data contracts is consistent with the approach to xml and binary serialization.

static void Main(string[] args)
{
    var ppl = new Person[] { new Person("John", "Smith"), new Person("Jane","Doe"),
        new Employee("Sally","Johnson"),new Person("Alejandro", "Cruz"),
        new Person("Diago","Pendaz"), new Employee("Tim","Chan")};

    //using xml Serialization
    var xmlSerializer = new DataContractSerializer(typeof(Person[]));
    using (var fs = new FileStream(@"c:\temp\data.xml", FileMode.Create, FileAccess.Write))
        xmlSerializer.WriteObject(fs, ppl);

    //using xml Deserialization
    Person[] pplXml;
    using (var fs = new FileStream(@"c:\temp\data.xml", FileMode.Open, FileAccess.Read))
        pplXml = xmlSerializer.ReadObject(fs) as Person[];

    foreach (var p in pplXml)
        Console.WriteLine(p.FullName);

    //using json Serialization
    var jsonSerializer = new DataContractJsonSerializer(typeof(Person[]));
    using (var fs = new FileStream(@"c:\temp\data.json", FileMode.Create, FileAccess.Write))
        jsonSerializer.WriteObject(fs, ppl);

    //using json Deserialization
    Person[] pplJson;
    using (var fs = new FileStream(@"c:\temp\data.json", FileMode.Open, FileAccess.Read))
        pplJson = jsonSerializer.ReadObject(fs) as Person[];

    foreach (var p in pplJson)
        Console.WriteLine(p.FullName);

}

The patter for serialization is very consistent between the three Microsoft methods

  • declare your serializer
  • open a stream to a data source
  • write to or read from your stream
Now our xml result is
<ArrayOfPerson
  xmlns="http://schemas.datacontract.org/2004/07/pc.SerializationDataContractsExample"
  xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Person>
    <FirstName>John</FirstName>
    <LastName>Smith</LastName>
  </Person>
  <Person>
    <FirstName>Jane</FirstName>
    <LastName>Doe</LastName>
  </Person>
  <Person i:type="Employee">
    <FirstName>Sally</FirstName>
    <LastName>Johnson</LastName>
    <Id>0</Id>
  </Person>
  <Person>
    <FirstName>Alejandro</FirstName>
    <LastName>Cruz</LastName>
  </Person>
  <Person>
    <FirstName>Diago</FirstName>
    <LastName>Pendaz</LastName>
  </Person>
  <Person i:type="Employee">
    <FirstName>Tim</FirstName>
    <LastName>Chan</LastName>
    <Id>1</Id>
  </Person>
</ArrayOfPerson>

and our json result is


[
  { "FirstName": "John""LastName": "Smith" },
  { "FirstName": "Jane""LastName": "Doe" },
  { "__type": "Employee:#pc.SerializationDataContractsExample",
    "FirstName": "Sally""LastName": "Johnson""Id": 0 },
  { "FirstName": "Alejandro""LastName": "Cruz" },
  { "FirstName": "Diago""LastName": "Pendaz" },
  { "__type": "Employee:#pc.SerializationDataContractsExample",
    "FirstName": "Tim""LastName": "Chan""Id": 1 }
]


No earlier i specified "Microsoft" methods because there's a 4th serialization which from my experience is fare more widely used then any of the ones i've discussed and that is the NewtonSoft serializer