Laden...

XML Serialisierung: List<string> wird nicht deserialisiert

Erstellt von fortuneNext vor 10 Jahren Letzter Beitrag vor 10 Jahren 4.896 Views
F
fortuneNext Themenstarter:in
45 Beiträge seit 2009
vor 10 Jahren
XML Serialisierung: List<string> wird nicht deserialisiert

verwendetes Datenbanksystem: <XML>

Hallo,
ich bin es gleich nochmal.

Ich habe ein Problem mit dem Deserialisieren einer sich in einem Objekt befindlichen List<string>.

Meine Klasse XmlStrucutralAccount enthält eine List<string>. Ich möchte sie mit einem XmlSerializer serialisieren. Folgende Datei ist die Ausgabe meines Beispielsets:

<?xml version="1.0"?>
<ArrayOfXmlAccount xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <XmlAccount xsi:type="XmlValueAccount">
    <Name>AktivKonto</Name>
    <AccountType>Active</AccountType>
    <StartValue>150</StartValue>
  </XmlAccount>
  <XmlAccount xsi:type="XmlValueAccount">
    <Name>PassivKonto</Name>
    <AccountType>Passive</AccountType>
    <StartValue>-15</StartValue>
  </XmlAccount>
  <XmlAccount xsi:type="XmlUserAccount">
    <Name>User</Name>
    <AccountType>User</AccountType>
    <StartValue>0</StartValue>
    <Email>test@mail.de</Email>
  </XmlAccount>
  <XmlAccount xsi:type="XmlStructuralAccount">
    <Name>Strukturkonto</Name>
    <AccountType>Active</AccountType>
    <subaccounts>
      <string>AktivKonto</string>
      <string>PassivKonto</string>
      <string>User</string>
    </subaccounts>
  </XmlAccount>
</ArrayOfXmlAccount>

Dabei kann man unter dem 4. Punkt sehen, dass die Liste <subaccounts> korrekt serialisiert wird.
Beim Deserialisieren bleibt die Liste "subaccounts" jedoch leer! Alles andere wird absolut korrekt eingelesen. Was könnte ich falsch gemacht haben?

Weitere Informationen: XmlStructuralAccount ist eine Unterklasse von XmlAccount (abstract), ebenso XmlValueAccount. XmlUserAccount ist wiederum eine Unterklasse von XmlValueAccount. Ich habe jeweils [XmlInclude(typeof(Unterklasse(n))] vor die Klassen gesetzt, weitere [] Attribute habe ich nicht gesetzt.
Kommandos, die ich benutze:

XmlSerializer serializer = new XmlSerializer(typeof(List<XmlAccount>)); // zum schreiben
List<XmlAccount> xmlAccounts = (List<XmlAccount>)serializer.Deserialize(streamReader); // zum lesen

Insgesamt handelt es sich also um eine List<Account>, die serialisiert werden soll.

Ich habe die Vermutung, dass ich vielleicht irgendwelche Attribute fehlen? Aber warum wird die Datei dann korrekt geschrieben, jedoch nicht gelesen?

Vielleicht hat ja jemand eine Idee. 😃
Freundliche Grüße
fortuneNext

5.658 Beiträge seit 2006
vor 10 Jahren

Hi fortuneNext,

Beim Deserialisieren bleibt die Liste "subaccounts" jedoch leer! Alles andere wird absolut korrekt eingelesen. Was könnte ich falsch gemacht haben?

Wie soll da jemand etwas dazu sagen, ohne die XmlAccount-Klasse zu kennen?
Bitte beachte [Hinweis] Wie poste ich richtig?, Punkt 5.

Christian

Weeks of programming can save you hours of planning

61 Beiträge seit 2009
vor 10 Jahren

Ich könnte hier zwei Aussagen zu machen:

  1. Je nach Implementierung der Klasse, in der sich die Liste befindet, konnte diese nicht erfolgreich deserialisiert werden, weil dort etwas an Code vorhanden ist, was den Mechanismus zu deserialisieren beeinflusst.

Hier muss ich dem guten "MrSparkle" zustimmen.
Ohne weitere Informationen wird niemand imstande sein eine passende Lösung vorzuschlagen oder zumindest zu helfen, den richtigen Weg zu finden.

  1. Ein Alternative wäre (ohne zu Wissen was in der Klasse implemtiert ist) auch mal den DataContractSerializer auszuprobieren.
    Der kann auch Objekte nach XML serialisieren und umgekehrt.
    Auseinandersetzen kannst man sich damit auf dieser Seite:
    DataContractSerializer-Klasse

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.

F
fortuneNext Themenstarter:in
45 Beiträge seit 2009
vor 10 Jahren

Hi,

Entschuldigung, das wäre natürlich sinnvoll gewesen! Da die Klassen recht trivial sind, hatte ich das fälschlicherweise als irrelevant angenommen. Mein Fehler.

Hier die beiden Definitionen:

[XmlInclude(typeof(XmlStructuralAccount)), XmlInclude(typeof(XmlValueAccount))]
    public abstract class XmlAccount
    {
        public string Name { get; set; }

        public AccountTypes AccountType { get; set; }
    }

[XmlInclude(typeof(List<String>))] // brauch ich das überhaupt? klappt ohne auch nicht
    public class XmlStructuralAccount : XmlAccount
    {
        public List<string> Subaccounts;

        public XmlStructuralAccount() { }

        public XmlStructuralAccount(StructuralAccount origin)
        {
            Name = origin.Name;
            AccountType = origin.AccountType;
            Subaccounts = new List<string>();
            foreach (Account account in origin.Subaccounts)
            {
                Subaccounts.Add(account.Name);
            }
        }
    }

Ich denke, die anderen beiden Klassen sind wirklich irrelevant.

Gruß
fortuneNext

16.835 Beiträge seit 2008
vor 10 Jahren

Ich mein Du brauchst die XML angaben per Attribute nicht, sondern musst dem Serializer die Typen mitgeben.

Sprich sowas wie

var typeList = new List<Type>( );
typeList.Add( typeof( XmlStructuralAccount  ) );

var xmlSerializer = new XmlSerializer( typeof( XmlAccount ), typeList.ToArray( ) );

bzw. könnte auch typeof ( XmlAccount [] ) sein.

F
fortuneNext Themenstarter:in
45 Beiträge seit 2009
vor 10 Jahren

Hi,

kann es grade nicht ausprobieren, werde ich morgen tun.
Allerdings frage ich mich, warum er dann die Datei korrekt schreibt und nur beim Lesen ausgerechnet nur dieses eine Feld leer bleibt, alle anderen aber wunderbar funktionieren?
(Die Attribute hab ich übrigens eingefügt, weil der Compiler mir das so gesagt hat. 😃 )

Gruß
fortuneNext

F
fortuneNext Themenstarter:in
45 Beiträge seit 2009
vor 10 Jahren

Ha, habe doch alles nötige hier.

Also nach dieser Methode zum Laden bekomme ich die Exceptions:

Fehlermeldung:
{"<ArrayOfXmlAccount xmlns=''> wurde nicht erwartet."}

bzw.> Fehlermeldung:

Das Objekt des Typs "Aktivenkasse.XmlAccount[]" kann nicht in Typ "System.Collections.Generic.List`1[Aktivenkasse.XmlAccount]" umgewandelt werden.

2.298 Beiträge seit 2010
vor 10 Jahren

Ich hab mir jetzt mal deine Klasse genommen und die Serialisierung / Deserialisierung getestet.
Bei mir wird die Liste deserialisiert. Ich vermute aber, es liegt an meiner Modifikation deiner Klasse.


public class XmlStructuralAccount : XmlAccount
{
	public List<string> Subaccounts = new List<string>();
}

Allgemein fährst du besser, wenn du Subaccounts zu einer Property machst. Dann funktioniert es auch ohne Initialisierung der Collection:


public class XmlStructuralAccount : XmlAccount
{
	private List<string> _subaccounts;
	public List<string> Subaccounts
	{
		get { return _subaccounts; }
		set { _subaccounts = value; }
	}
}

Meine Methode zum deserialisieren sieht wie folgt aus:


static List<XmlAccount> Deserialize()
{
	List<XmlAccount> accounts = new List<XmlAccount>();

	XmlSerializer serializer = new XmlSerializer(typeof(List<XmlAccount>));
	Stream stream = File.Open("test.xml", FileMode.OpenOrCreate, FileAccess.ReadWrite);
	accounts = (List<XmlAccount>)serializer.Deserialize(stream);
	stream.Close();

	return accounts;
}

Ich hoffe das hilft dir. - Die Methode Deserialize eignet sich so aber nicht für Produktivcode.

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

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

F
fortuneNext Themenstarter:in
45 Beiträge seit 2009
vor 10 Jahren

Tatsächlich, das hat die Lösung gebracht. Vielen vielen Dank!