Question

I have problem deserializing list of list in my xml file:

<?xml version="1.0" encoding="UTF-8"?>
<RootLevel><!--Container-->
   <ListOfOne><!--List of One -->
      <One>
         <ListOfTwo> <!--List of Two -->
            <Two></Two>
         </ListOfTwo>
      </One>
   </ListOfOne>
</RootLevel>

RootLevel has List of One. One has List of Two

The first level (ListOfOne) is working file with out any problem, the problem is that the ListOfTwo is not being deserialized

[KnownType(typeof(List<One>))]
    [DataContract(Name = "RootLevel", Namespace = "")]
    public sealed class RootLevel
    {
        [DataMember()]
        public List<One> ListOfOne { get; set; }

        public RootLevel()
        {
            ListOfOne = new List<One>();
        }
    }

[DataContract(Name = "One", Namespace = "")]
    [KnownType(typeof(List<Two>))]
    public sealed class One
    {
        public One()
        {
            ListOfTwo = new List<Two>();
        }
        [OnDeserialized]
        internal void OnSerializingMethod(StreamingContext context)
        {
            ListOfTwo = new List<Two>();
        }

        [DataMember]
        public List<Two> ListOfTwo { get; set; }
}

[DataContract(Name = "Two", Namespace = "")]
    public sealed class Two
    {}

This is the operation:

 using (var fs = new FileStream("path to file", FileMode.Open))
            {

                using (var reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()))
                {
                    DataContractSerializer ser = new DataContractSerializer(typeof(RootLevel));

                    var deserializedPerson = (RootLevel)ser.ReadObject(reader, true);
                    Assert.IsTrue(deserializedPerson.ListOfOne[0].ListOfTwo.Count > 0);
                    reader.Close();
                    fs.Close();
                }
            }
Was it helpful?

Solution

If you drop this part of the code everything works as expected:

[OnDeserialized]
internal void OnSerializingMethod(StreamingContext context)
    ListOfTwo = new List<Two>();
}

If you wish to make sure you always have an empty ListOfTwo change it to:

[OnDeserialized]
internal void OnSerializingMethod(StreamingContext context)
{
    if(ListOfTwo == null) {
        ListOfTwo = new List<Two>();
    }
}

I ran the code with a small modification (not reading from file)

string xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
                <RootLevel> <!--Container-->
                   <ListOfOne> <!--List of One -->
                      <One>
                        <ListOfTwo> <!--List of Two -->
                           <Two></Two>
                        </ListOfTwo> 
                     </One>
                   </ListOfOne>
                 </RootLevel>";

var stream = new MemoryStream(Encoding.Default.GetBytes(xml));

using (var reader = XmlDictionaryReader
                           .CreateTextReader(stream, 
                                             new XmlDictionaryReaderQuotas()))
{
    DataContractSerializer ser = new DataContractSerializer(typeof(RootLevel));

    var deserializedPerson = (RootLevel)ser.ReadObject(reader, true);
    Assert.IsTrue(deserializedPerson.ListOfOne[0].ListOfTwo.Count > 0);
    reader.Close();
}

with this contract change

[DataContract(Name = "One", Namespace = "")]
[KnownType(typeof(List<Two>))]
public sealed class One
{
    public One()
    {
        ListOfTwo = new List<Two>();
    }

    [OnDeserialized]
    internal void OnSerializingMethod(StreamingContext context)
    {
        if (ListOfTwo == null)
        {
            ListOfTwo = new List<Two>();
        }
    }

    [DataMember]
    public List<Two> ListOfTwo { get; set; }
}

And the Assert is fine, ListOfTwo has one object as expected.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top