Forum guidelines
AuthorQuestion
Import/Export Generic List Objects
Posted on: 07 May 2013
I have a number of list (objects?).

For example:

private System.Collections.Generic.List<Person> Person;
this.People = new System.Collections.Generic.List<Person>();

What I'd like to do is somehow export these lists out..don't mind what format..flatfile..whatever..

And then be able to import them in "recreating" the list (object?)

Any direction would be appriciated.

Thanks,

AuthorReply
Vulpes
  • 0
  • 0
accepted
Re: Import/Export Generic List Objects
Posted on: 09 May 2013   Accepted Answer
Yes, the problem is that most control characters, including the null character 0x00, are invalid in XML.

However, as you suggest yourself, you can get around this by using an XmlTextReader whose Normalization property is set (by default) to false. The one which the Deserialize method uses under the hood has its Normalization property set to true.

Here's my original example changed to use an XmlTextReader which is slightly simpler than what you already have:

using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

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

class Test
{
   static void Main()
   {
      var people = new List<Person>();
      var p = new Person();
      p.Name = "Jay\0"; 
      people.Add(p);
      var p2 = new Person();
      p2.Name = "Vulpes";
      people.Add(p2);

      var xs = new XmlSerializer(typeof(List<Person>));
      // serialize to disk
      using (Stream s = File.Create("Persons.xml")) 
      {      
         xs.Serialize(s, people);
      }

      // deserialize to a new list

      List<Person> people2;
      using(Stream s = File.OpenRead("Persons.xml"))
      {
         using(XmlTextReader reader = new XmlTextReader(s))
         {
            people2 = (List<Person>)xs.Deserialize(reader); 
         }
      }

      // check it worked
      foreach(Person pers in people2) Console.WriteLine(pers.Name);
      Console.ReadKey();
   }
}




Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
An easy approach is to use XML serialization to serialize your list to disk.

Here's some sample code:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;

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

class Test
{
   static void Main()
   {
      var people = new List<Person>();
      var p = new Person();
      p.Name = "Jay";
      people.Add(p);
      var p2 = new Person();
      p2.Name = "Vulpes";
      people.Add(p2);

      var xs = new XmlSerializer(typeof(List<Person>));
 
      // serialize to disk
      using (Stream s = File.Create("Persons.xml")) 
      {
         xs.Serialize(s, people);
      }

      // deserialize to a new list

      List<Person> people2;
      using(Stream s = File.OpenRead("Persons.xml"))
      {
         people2 = (List<Person>)xs.Deserialize(s);
      }

      // check it worked
      foreach(Person pers in people2) Console.WriteLine(pers.Name);
      Console.ReadKey();
   }
}




Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
Is :

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

The class that initially creates the list in question?

In one object list I have 32 objects(not sure on terminology) per item and there may be 5000 items in the list ( so 5000 persons with 32 pieces of information attached to them)

Does this mean on

      var p = new Person();
      p.Name = "Jay";
      people.Add(p);
      var p2 = new Person();
      p2.Name = "Vulpes";
      people.Add(p2);


I'd have to manually write out each and every one?

One of my lists is like this (sorry for the doctering)



Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
My Person class was just the simplest of examples. In practice, serialization works just as well with 32 properties as one.

Also it doesn't matter how many elements there are in the List which you'll already have populated before serialization takes place. 

It'll produce a large XML file, of course, but I'd try it and see if it works 'straight out of the box'.

There are a number of reasons why it may not work immediately but these are usually easily fixed by decorating some properties with suitable attributes.


Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
It errors "out of the box".

There was an error reflecting type 'System.Collections.Generic.List`1[Foo.Person]'.

I really do think this is way above my head...I don't even understand what each part is, what to replace them with from my code...completely confused!

Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
This is the code to concentrate on which serializes a List<Person> called 'people' to disk and then deserializes it back to a new List<Person> called 'people2'.

      var xs = new XmlSerializer(typeof(List<Person>));
      // serialize to disk
      using (Stream s = File.Create("Persons.xml")) 
      {
         xs.Serialize(s, people);
      }

      // deserialize to a new list

      List<Person> people2;
      using(Stream s = File.OpenRead("Persons.xml"))
      {
         people2 = (List<Person>)xs.Deserialize(s);
      }

It really is quite simple compared to other approaches such as CSV files where you'd need to specify each property individually when writing the list elements to the file and reading them back.

Under the hood, the serializer figures out using reflection which properties you have and then writes their values to the XML file so you are relieved from doing this 'manually'.

Do you have any more information on the error which may give us a clue as to what's wrong?



Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
Erroring on this line:

var xs = new XmlSerializer(typeof(List<Person>));

With:

There was an error reflecting type 'System.Collections.Generic.List`1["namespace".Person]

I don't actually have a list call List`1 which I find very odd?






Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
List`1 is just how a generic list is referred to by the CLR.

One reason why serialization often fails is because the type you're trying to serialize has no parameterless constructor which (for technical reasons) it needs to have.

If your Person class has a constructor which takes no parameters (or it has no constructor at all) then this can't be the reason.

However, if the only constructor which it does have takes parameters, then add this line to the Person class and try serializing again:

public Person(){} 

Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
My terminolgy is pretty poor..

What does "no parameterless constructor" mean, i.e. how can I tell?

In my Person Class I already have:

public Person()
{
}

Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
That is a parameterless constructor (it takes no parameters) and so this can't be the reason why serialization is failing.

Can you list the types of your 32 properties please. You can ignore simple stuff such as int, long, double, bool, char, string etc.

Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
I have..

int, strings, shorts, bytes..

I also have:

public FooDate ClubContractStart;

Where FooDate is a class.

public class FooDate
{
public short Day;
public short Year;
public FooDate(short day, short year)
{
this.Day = day;
this.Year = year;
}
}

I also have:

public Player PlayingData;
public NonPlayer NonPlayingData;

Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
Ah, FooDate has no parameterless constructor so give it one:

public FooDate(){}

Do the same for Player and NonPlayer if needed, then try to serialize again.



Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
It works surprisingly well! (only serialized initially)

Only concern is...

Because Person "calls"/"Uses" :

public Player PlayingData;
public NonPlayer NonPlayingData;

Both of these are lists in there own rights and the serialization popped these all in the XML as well so its almost like its combined everything up...

Re: Import/Export Generic List Objects
Posted on: 07 May 2013  
When you have objects which contain other objects, the serializer serializes those other objects as well and automatically recognizes arrays, lists etc.

So I'd expect it to all to work now.

Might be best though to serialize a list containing a single Person object, then deserialize it to make sure all layers of objects are being recreated correctly.

Re: Import/Export Generic List Objects
Posted on: 08 May 2013  
So if "Person" also contains a reference to 

public Player PlayingData;
public NonPlayer NonPlayingData;

Both a seperate lists in there own right serilization will serializes  these as well and when importing them back in will re-create the as their own uinique lists?

Also..

using (Stream s = File.Create("Persons.xml")) 
      {
         xs.Serialize(s, people);
      }

What is "people" meant to be replaced with?

Re: Import/Export Generic List Objects
Posted on: 08 May 2013  
You're correct, Jay, on the first point.

On the second point, 'people' should be replaced with whatever List<Person> object you're trying to serialize. So, if you had another list called 'people2', you'd use that instead.

Re: Import/Export Generic List Objects
Posted on: 08 May 2013  
Can't seem to send you a private message (not enough points) with code I'd prefer not to show in the public..any way around this?
Re: Import/Export Generic List Objects
Posted on: 08 May 2013  
AFAIK, any member can send me a private message so I'd have another go.

If it still doesn't work, I'll try sending you one and see if you can then reply to it.

However, I'm going out now for a few hours so it will be a while before I can reply to it in any case.

Re: Import/Export Generic List Objects
Posted on: 08 May 2013  
I was just going to share exactly what I'm doing/try to do in fullness, rather than changing namespaces, list names etc and may give you more context what I'm actually trying to achieve.

If there's no way around it I will just go via this...

Re: Import/Export Generic List Objects
Posted on: 08 May 2013  
I definatly need 100 points to be able to send a private message :/ oh well...only another 50 points left

Is there any way to NOT serialize those lists referenced in the list/object being serialized...so some sort of skip over?

Re: Import/Export Generic List Objects
Posted on: 08 May 2013  
It must be something the admins have implemented recently.

We have had problems in the past with members being spammed by folks who'd joined especially for that purpose - 'lonely women' and the like -  so they're probably trying to stop that by imposing a minimum points requirement to send a message.

Anyway, the answer to your question is that you can prevent a public property or field from being serialized by decorating it with the [XmlIgnore] attribute. For example:

class MyClass
{
    public int MyInt; // this will be serialized

   [XmlIgnore]
    public List<int> List; // this won't be
}

Re: Import/Export Generic List Objects
Posted on: 09 May 2013  
So...this:

[XmlIgnore]
    public List<int> List; // this won't be

Goes in my list/object class and NOT the function which is doing the serialization?

Re: Import/Export Generic List Objects
Posted on: 09 May 2013  
That's right, you have to put these attributes inside the class to be serialized.

They have no effect otherwise.

Re: Import/Export Generic List Objects
Posted on: 09 May 2013  
When I "deserialize" these back into lists, will the keep their same formats/types?
Re: Import/Export Generic List Objects
Posted on: 09 May 2013  
Yes, they should be exactly the same.
Re: Import/Export Generic List Objects
Posted on: 09 May 2013  
Sorry,

Does [XmlIgnore] only effect up to the ";" so will have to do for each one?

Re: Import/Export Generic List Objects
Posted on: 09 May 2013  
That's right.

You have to apply the attribute to each property or field to be ignored by the serializer.

Re: Import/Export Generic List Objects
Posted on: 09 May 2013  
When I deserialize it I do actually get an error:

There is an error in XML document (16, 24)

Inner Exception:

{"'.', hexadecimal value 0x00, is an invalid character. Line 16, position 24."}

I'm guessing its due to the fact I have a value like:

Italy\0n\0\0\0

And its seeing this as hex or something..

I'm not to sure how to get by this..maybe wrap it in a text reader!?

EDIT:

Maybe...


            // deserialize to a new list
            TextReader tr = null;
            List<Person> people2;
            using (Stream s = File.OpenRead("C://Temp/Persons.xml"))
            {
                s.Position = 0;
                tr = new StreamReader(s);
                XmlTextReader xtr = new XmlTextReader(tr);
                people2 = (List<Person>)xs.Deserialize(xtr);
            }

Re: Import/Export Generic List Objects
Posted on: 10 May 2013  
Once again thank you Vulpes.

Successfully serialized my list/objects and deserialized them on another machine.



SPONSORED BY

Offshore Software and Database Development
MCN is your source for developing solutions involving websites, mobile apps, cloud-computing, databases, BI, back-end services and processes and client-server applications.