Laden...

Deserialisieren einer Property vom Typ List

Erstellt von csharp_benutzer vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.719 Views
C
csharp_benutzer Themenstarter:in
20 Beiträge seit 2013
vor 10 Jahren
Deserialisieren einer Property vom Typ List

Hallo,

der Xml-Serializer serialisiert mir folgende Klasse problemlos. Aber beim Deserialisieren wird die Liste von Books nicht befüllt (null value).

Könnt ihr bitte einen Blick werfen, ob ich meine Klasse falsch konfiguriert habe?



[XmlRootAttribute("Test")]
public class TestClass
{
        [XmlElement("Name")]
        public string Name { get; set; }

        [XmlElement("Id")]
        public string Id { get; set; }

        [XmlArray("Books")]
        [XmlArrayItem("Book", typeof(Book))]
        public List<Book> Books { get; set; }
}

public class Book
{
        [XmlElement("Title")]
        public string Title { get; set; }

        [XmlElement("Author")]
        public string Author { get; set; }

}

W
872 Beiträge seit 2005
vor 10 Jahren

Du musst meines Erachtens noch

[XmlInclude(typeof(Book))]

zum Rootelement hinzufügen.
Siehe auch XmlIncludeAttribute-Klasse.

2.079 Beiträge seit 2012
vor 10 Jahren

Wenn du uns auch noch zeigst, wie du serialisierst/deserialisierst, dann vielleicht.

Abgesehen davon kannst du XmlElement weg lassen, wenn der Name dre Gleiche bleibt.
Ist das nicht gesetzt, wird der Name der Property/Klasse verwendet.

@weismat:

Nicht zwangsläufig, zumindest habe ich es nie gebraucht.

Das brauch man - so wie ich das verstanden habe - nur dann, wenn irgendein Basistyp verwendet wird, aber tatsächlich ein anderer abgeleiteter Typ drin steht.

Also z.B. wenn eine Property vom Typ object ist, aber eigentlich Book enthält.

C
csharp_benutzer Themenstarter:in
20 Beiträge seit 2013
vor 10 Jahren

Hier ist der Code für Serialize (testClassData ist ein Objekt von TestClass)



var xmlWritterSettings = new XmlWriterSettings();
xmlWritterSettings.OmitXmlDeclaration = true;
xmlWritterSettings.Indent = true;

var xmlSerializer = new XmlSerializer(typeof(TestClass));
var xmlnsEmpty = new XmlSerializerNamespaces(new[] { new XmlQualifiedName(String.Empty, String.Empty) });

string serializedString = string.Empty;

using (var stringWriter = new StringWriter())
using (var xmlWriter = XmlWriter.Create(stringWriter, xmlWritterSettings))
{
      xmlSerializer.Serialize(xmlWriter, testClassData, xmlnsEmpty);
      serializedString = stringWriter.ToString();
      stringWriter.Close();
}


Hier ist der Code für Deserialize:



var xmlSerializer = new XmlSerializer(typeof(TestClass));
TestClass testClassData;

using (var stringReader = new StringReader(xmlString))
{
       testClassData= (TestClass)xmlSerializer.Deserialize(stringReader);
       stringReader.Close();
}


Beim Deserialisieren wird die Liste von Books nicht mit Daten gefüllt, obwohl ich welche in Xml-String habe.

Ich habe gerade noch was probiert: wenn ich statt List ein Array verwende, dann wird Books doch mit Daten befüllt. Ich würde aber gerne List verwenden, weil es einfacher zu handhaben ist.

16.825 Beiträge seit 2008
vor 10 Jahren

Du musst unbekannte Typen dem Serializer bekannt machen.

var xmlSerializer = new XmlSerializer( typeof( TestClass ), new Type[ ]  { typeof( Book ) } );
C
csharp_benutzer Themenstarter:in
20 Beiträge seit 2013
vor 10 Jahren

Du musst unbekannte Typen dem Serializer bekannt machen.

var xmlSerializer = new XmlSerializer( typeof( TestClass ), new Type[ ]  { typeof( Book ) } );  

hat leider nicht geholfen...

2.298 Beiträge seit 2010
vor 10 Jahren

Wie sieht denn das generierte Xml aus?

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

T
94 Beiträge seit 2007
vor 10 Jahren

Benutze folgende XmlHelper Klasse.

Deine Testklasse:


public class TestClass
{
  private List<Book> books = new List<Book>();

  public string Name { get; set; }

  public string Id { get; set; }

  public List<Book> Books
  { 
    get { return this.books; } 
  }
}

public class Book
{
  public string Title { get; set; }

  public string Author { get; set; }
}

XML Serialisieren und wieder zurück.


TestClass tc = new TestClass() { Id = "1", Name = "Test" };
tc.Books.Add(new Book() { Author = "Hans Meyer", Title = "Das Buch" });

var erg = XMLHelper.SerializeToXMLString(tc, Encoding.Default, true);

TestClass tc2 = XMLHelper.DeserializeFromXMLString<TestClass>(erg);

2.079 Beiträge seit 2012
vor 10 Jahren

Also ich persönlich nutze immer Folgende zwei Methoden:

public static void SerializeFile<T>(string filePath, T obj)
{
    var serializer = new XmlSerializer(typeof(T));
    using (var fileStream = File.OpenWrite(filePath))
        serializer.Serialize(fileStream, obj);
}
public static T DeSerializeFile<T>(string filePath)
{
    var serializer = new XmlSerializer(typeof(T));
    using (var fileStream = File.OpenRead(filePath))
        return (T)serializer.Deserialize(fileStream);
}

Anpassungen sind nicht weiter schwer, so nutze ich auch manchmal den Weg, dass ein Stream als Parameter verlangt wird und dann wird in den geschrieben, oder aus ihm gelesen.

Das funktioniert bei mir komplett fehlerfrei, genutzt habe ich die zwei Klassen aus dem Anfangspost, inklusive der Attribute.

So teste ich das ganze, mit einem Breakpoint danach:

var book1 = new Book() { Author = "Author1", Title = "Title1" };
var book2 = new Book() { Author = "Author2", Title = "Title2" };

var testClass1 = new TestClass();
testClass1.Id = "Id1";
testClass1.Name = "Name1";
testClass1.Books = new List<Book>();
testClass1.Books.Add(book1);
testClass1.Books.Add(book2);
testClass1.Books.Add(book1);

var testClass2 = new TestClass();
testClass2.Id = "Id2";
testClass2.Name = "Name2";
testClass2.Books = new List<Book>();
testClass2.Books.Add(book2);
testClass2.Books.Add(book1);
testClass2.Books.Add(book2);

var testClassList = new List<TestClass>();
testClassList.Add(testClass1);
testClassList.Add(testClass2);

SerializeFile("testXml.txt", testClassList);

var daten = DeSerializeFile<List<TestClass>>("testXml.txt");("testXml.txt");

DIE XML-Datei:

<?xml version="1.0"?>
<ArrayOfTestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TestClass>
    <Name>Name1</Name>
    <Id>Id1</Id>
    <Books>
      <Book>
        <Title>Title1</Title>
        <Author>Author1</Author>
      </Book>
      <Book>
        <Title>Title2</Title>
        <Author>Author2</Author>
      </Book>
      <Book>
        <Title>Title1</Title>
        <Author>Author1</Author>
      </Book>
    </Books>
  </TestClass>
  <TestClass>
    <Name>Name2</Name>
    <Id>Id2</Id>
    <Books>
      <Book>
        <Title>Title2</Title>
        <Author>Author2</Author>
      </Book>
      <Book>
        <Title>Title1</Title>
        <Author>Author1</Author>
      </Book>
      <Book>
        <Title>Title2</Title>
        <Author>Author2</Author>
      </Book>
    </Books>
  </TestClass>
</ArrayOfTestClass>

Und auch eingelesen ist alles richtig.

Wenn das nicht funktioniert, ist es ein Problem im Code von dir.