Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems deserializing List of objects

I am having trouble deserializing a list of objects. I can get just one object to serialize into an object but cannot get the list. I get no error it just returns an empty List. This is the XML that gets returned:

<locations>
   <location locationtype="building" locationtypeid="1">
     <id>1</id>
     <name>Building Name</name>
     <description>Description of Building</description>
   </location>
</locations>

This is the class I have and I am deserializing in the GetAll method:

[Serializable()]
[XmlRoot("location")]
public class Building
{
    private string method;

    [XmlElement("id")]
    public int LocationID { get; set; }
    [XmlElement("name")]
    public string Name { get; set; }
    [XmlElement("description")]
    public string Description { get; set; }
    [XmlElement("mubuildingid")]
    public string MUBuildingID { get; set; }

    public List<Building> GetAll()
    {
        var listBuildings = new List<Building>();
        var building = new Building();
        var request = WebRequest.Create(method) as HttpWebRequest;
        var response = request.GetResponse() as HttpWebResponse;

        var streamReader = new StreamReader(response.GetResponseStream());
        TextReader reader = streamReader;
        var serializer = new XmlSerializer(typeof(List<Building>), 
            new XmlRootAttribute() { ElementName = "locations" });
        listBuildings = (List<Building>)serializer.Deserialize(reader);

        return listBuildings;
    }
}
like image 734
Andy Xufuris Avatar asked Aug 21 '13 20:08

Andy Xufuris


2 Answers

Try this:

[XmlRoot("locations")]
public class BuildingList
{
    public BuildingList() {Items = new List<Building>();}
    [XmlElement("location")]
    public List<Building> Items {get;set;}
}

Then deserialize the whole BuildingList object.

var xmlSerializer = new XmlSerializer(typeof(BuildingList));
var list = (BuildingList)xmlSerializer.Deserialize(xml);
like image 76
drwatsoncode Avatar answered Sep 25 '22 14:09

drwatsoncode


I know this is an old(er) question, but I struggled with this today, and found an answer that doesn't require encapsulation.

Assumption 1: You have control over the source Xml and how it is constructed.

Assumption 2: You are trying to serialise the Xml directly into a List<T> object

  1. You must name the Root element in the Xml as ArrayOfxxx where xxx is the name of your class (or the name specified in XmlType (see 2.))
  2. If you wish your xml Elements to have a different name to the class, you should use XmlType on the class.

NB: If your Type name (or class name) starts with a lowercase letter, you should convert the first character to uppercase.

Example 1 - Without XmlType

class Program
{
    static void Main(string[] args)
    {
        //String containing the xml array of items.
        string xml =
@"<ArrayOfItem>
    <Item>
        <Name>John Doe</Name>
    </Item>
    <Item>
        <Name>Martha Stewart</Name>
    </Item>
</ArrayOfItem>";


        List<Item> items = null;
        using (var mem = new MemoryStream(Encoding.Default.GetBytes(xml)))
        using (var stream = new StreamReader(mem))
        {
            var ser = new XmlSerializer(typeof(List<Item>)); //Deserialising to List<Item>
            items = (List<Item>)ser.Deserialize(stream);
        }

        if (items != null)
        {
            items.ForEach(I => Console.WriteLine(I.Name));
        }
        else
            Console.WriteLine("No Items Deserialised");

    }
}

public class Item
{
    public string Name { get; set; }
}

Example 2 - With XmlType

class Program
{
    static void Main(string[] args)
    {
        //String containing the xml array of items.
        //Note the Array Name, and the Title case on stq.
        string xml =
@"<ArrayOfStq>
    <stq>
        <Name>John Doe</Name>
    </stq>
    <stq>
        <Name>Martha Stewart</Name>
    </stq>
</ArrayOfStq>";


        List<Item> items = null;
        using (var mem = new MemoryStream(Encoding.Default.GetBytes(xml)))
        using (var stream = new StreamReader(mem))
        {
            var ser = new XmlSerializer(typeof(List<Item>)); //Deserialising to List<Item>
            items = (List<Item>)ser.Deserialize(stream);
        }

        if (items != null)
        {
            items.ForEach(I => Console.WriteLine(I.Name));
        }
        else
            Console.WriteLine("No Items Deserialised");

    }
}

[XmlType("stq")]
public class Item
{
    public string Name { get; set; }
}
like image 21
Obsidian Phoenix Avatar answered Sep 23 '22 14:09

Obsidian Phoenix