Search code examples
c#datacontractserializer

DataContractSerializer - Not Deserializing Child List - List<T>


I'm trying to deserialize the following XML using DataContractSerializer.

<?xml version="1.0" encoding="utf-8"?>
<order>
  <header>
    <cust>1</cust>
    <bill>2</bill>
    <ship>3</ship>
    <nbr>123456</nbr>
  </header>
  <details>
    <detail>
      <nbr>123456</nbr>
      <part>1227</part>
      <qty>2</qty>
    </detail>
  </details>
</order>

I'm having difficulty deserializing the child <detail></detail> segment, which is always null. My class structure is as follows:

[DataContract(Name = "order", Namespace ="")]
public class Order
{
    [DataMember(Name = "header", Order = 0)]
    public Head head { get; set; }
    [DataMember(Name = "details", Order = 1)]
    public Details details { get; set; }

    public Order()
    {
    }
}

[DataContract(Name = "header", Namespace ="")]
public class Head
{
    [DataMember(Name = "cust", Order = 0)]
    public string customerNbr { get; set; }
    [DataMember(Name = "bill", Order = 1)]
    public string billNbr { get; set; }
    [DataMember(Name = "ship", Order = 2)]
    public string shipmentNbr { get; set; }
    [DataMember(Name = "nbr", Order = 3)]
    public string orderNbr { get; set; }

    public Head()
    {

    }
}

[DataContract(Name = "details")]
public class Details
{
    [DataMember(Name = "detail", Order = 0)]
    public List<Detail> DetailList { get; set; }

    public Details()
    {
        this.DetailList = new List<Detail>();
    }
}

[DataContract(Name = "detail")]
public class Detail
{
    [DataMember(Name = "nbr", Order = 0)]
    public string orderNbr { get; set; }
    [DataMember(Name = "part", Order = 1)]
    public string partNbr { get; set; }
    [DataMember(Name = "qty", Order = 2)]
    public decimal orderQty { get; set; }

    public Detail()
    {

    }
}

And in my main program, I'm reading the XML document and deserializing it using the following:

XDocument readDoc = XDocument.Load(fileName);
Order createOrder = null;
DataContractSerializer ser = new DataContractSerializer(typeof(Order));
createOrder = (Order)ser.ReadObject(readDoc.CreateReader());

What can I do to make the detail segment deserialize correctly?


Solution

  • The problem is that your data contract classes are different from the ones the actual xml structure requires.

    You can solve this by making a small modification to your models.

    Set the Namespace for Detail class to match the one in the other classes, i.e.: a blank value.

    [DataContract(Name = "detail", Namespace = "")]
    public class Detail
    {
        //same stuff here...
    }
    

    Make your Details class a collection to the data contract.

    [CollectionDataContract(Name = "details", Namespace = "")]
    public class Details : Collection<Detail> { }
    

    You can check this for more details about collection and data contract serialization.

    Hope this helps!