2017-10-17 5 views
4

Je le code XML suivant que je suis en train de désérialiser comme suit mais j'obtiens l'erreur:Impossible de désérialiser une chaîne XML

There was an error reflecting type 'System.Collections.Generic.List`1[MyApp.Models.Field]

Ci-dessous est mon code

public class FieldList 
{ 
    [XmlArray("fields")] 
    [XmlArrayItem("field")] 
    List<Field> Fields { get; set; } 
} 

public class Field 
{ 
    [XmlAttribute("type")] 
    public string Type { get; set; } 

    [XmlAttribute("required")] 
    public bool Required { get; set; } 

    [XmlAttribute("label")] 
    public string Label { get; set; } 

    [XmlAttribute("name")] 
    public string Name { get; set; } 

    [XmlElement("option")] 
    [JsonProperty("values")] 
    public List<Option> Options { get; set; } 
} 

public class Option 
{ 
    [XmlAttribute("label")] 
    public string Label { get; set; } 

    [XmlAttribute("value")] 
    public string Value { get; set; } 

    [XmlAttribute("selected")] 
    public bool Selected { get; set; } 

    /// <remarks/> 
    [XmlIgnore()] 
    public bool SelectedSpecified { get; set; } 

    [XmlText] 
    public string Text { get; set; } 
} 

var xml = @"<?xml version=""1.0"" ?> 
    <form-template> 
    <fields> 
     <field type=""select"" required=""true"" label=""Cars"" name=""cars"" > 
      <option label=""Toyota"" value=""Toyota"" selected=""true"">Toyota</option> 
      <option label=""Nisan"" value=""Nisan"" >Nisan</option> 
     </field> 
    </fields> 
    </form-template>"; 


var serializer = new XmlSerializer(typeof(FieldList), new XmlRootAttribute("form-template")); 
var stringReader = new StringReader(xml); 
var xmlFields = (FieldList)serializer.Deserialize(stringReader); 

Qu'est-ce que je fais faux?

* MISE À JOUR *

Selon les commentaires ci-dessous l'évolution

public IEnumerable<Option> Options { get; set; } 

Pour

public List<Option> Options { get; set; } 

corrige l'erreur mais maintenant rien est désérialisée - la xmlFields variable est vide ??? Ai-je besoin de lire à partir d'un nœud particulier ou ne devrait-il pas importer?

+0

Le 'InnerException' doit contenir un indice. –

+0

@ManfredRadlwimmer en changeant 'IEnumerable

+0

Ma meilleure supposition est que parce que la propriété suivante est une interface public IEnumerable

Répondre

2

Regardons votre code.

new XmlRootAttribute("form-template") correspond au noeud <form-template>.

public class Field correspond au noeud <field.

Mais rien ne correspond au noeud <fields>.

Ajouter classe suivante:

public class FieldList 
{ 
    [XmlArray("fields")] 
    [XmlArrayItem("field")] 
    public List<Field> Fields { get; set; } 
} 

Il devrait fonctionner:

var serializer = new XmlSerializer(typeof(FieldList), new XmlRootAttribute("form-template")); 
var stringReader = new StringReader(xml); 
var xmlFields = (FieldList)serializer.Deserialize(stringReader); 

En outre, vous devez ajouter une propriété à la classe Option:

[XmlText] 
public string Text { get; set; } 

Mise à jour. Vous pouvez supprimer la classe FieldList. Mais alors vous devez sauter manuellement une partie des nœuds xml.

List<Field> xmlFields; 
var serializer = new XmlSerializer(typeof(List<Field>), new XmlRootAttribute("fields")); 

// You can read from a stream or from a StringReader instead of a file 
using (var xmlReader = XmlReader.Create("test.xml")) 
{ 
    // Skip <form-template> node 
    xmlReader.ReadToFollowing("fields"); 

    xmlFields = (List<Field>)serializer.Deserialize(xmlReader); 
} 

Ajouter XmlType attribut à votre classe:

[XmlType("field")] 
public class Field 
+0

J'ai fait les modifications selon votre solution mais 'xmlFields' est toujours nul? – adam78

+0

est-il un moyen de commencer à lire le xml à partir du nœud '' afin que je puisse me débarrasser de la classe 'FieldList' sans modifier le xml existant? – adam78

+0

@ adam78 - voir mise à jour. –

3

XmlSerializer ne peut pas sérialiser propriétés abstraites donc s'il vous plaît changer IEnumerable à la liste comme ci-dessous,

public IEnumerable<Option> Options { get; set; } 

à

public List<Option> Options { get; set; } 

élément racine Vous ne correspond pas à la structure XML que vous avez. J'ai édité XML comme ci-dessous,

var xml = "<?xml version=\"1.0\" ?>" + 
        " " + 
        " <Fields>" + 
        "  <Field Type=\"select\" Required=\"true\" Label=\"Cars\" Name=\"cars\" >" + 
        "   <option label=\"Toyota\" lalue=\"Toyota\" selected=\"true\">Toyota</option>" + 
        "   <option label=\"Nisan\" value=\"Nisan\" >Nisan</option>" + 
        "  </Field>" + 
        " </Fields>"; 

et codes désérialisation que,

XmlSerializer serializer = new XmlSerializer(typeof(List<Field>), new XmlRootAttribute("Fields")); 

    var stringReader = new StringReader(xml); 
     List<Field> xmlFields = (List<Field>)serializer.Deserialize(stringReader); 

Maintenant, il est bien désérialisation. S'il vous plaît voir la sortie,

enter image description here

+0

Passer à 'List

+0

La classe 'Option' est-elle marquée avec l'attribut' [Serializable] '? A-t-il un CTOR sans paramètre? – Moerwald

+0

@Moerwald - La classe 'XmlSerializer' n'utilise pas l'attribut' Serializable'. –

1

Vous devez générer les classes correctement auquel vous souhaitez sérialiser le fichier XML. Copiez votre code XML correct sans double "guillemets doubles" dans le presse-papiers, accédez à n'importe quel fichier cs dans la solution dans Visual Studio. Cliquez sur Édition-> Collage spécial-> Coller XML en classes. Cela va générer des classes correctement pour la conversion dans votre fichier cs. Ensuite, remplacez-les par des propriétés implémentées automatiquement au lieu d'utiliser des variables privées pour réduire l'encombrement à l'écran.

Avec l'ensemble des classes ci-dessous, deserialize comme

XmlSerializer serializer = new XmlSerializer(typeof(FormTemplate)); 
      var xml = @"<?xml version=""1.0"" ?> 
    <form-template> 
    <fields> 
     <field type=""select"" required=""true"" label=""Cars"" name=""cars"" > 
      <option label=""Toyota"" value=""Toyota"" selected=""true"">Toyota</option> 
      <option label=""Nisan"" value=""Nisan"" >Nisan</option> 
     </field> 
    </fields> 
    </form-template>"; 
      var stringReader = new StringReader(xml); 
      var xmlFields = serializer.Deserialize(stringReader); 

ensemble généré automatiquement des classes modifiées pour propriétés de modification des propriétés implémentées automatiquement.

/// <remarks/> 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
[System.Xml.Serialization.XmlRootAttribute("form-template", Namespace = "", IsNullable = false)] 
public partial class FormTemplate 
{ 
    /// <remarks/> 
    public Fields fields { get; set; } 
} 

/// <remarks/> 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
public partial class Fields 
{ 
    /// <remarks/> 
    public SingleField field { get; set; } 
} 

/// <remarks/> 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
public partial class SingleField 
{ 
    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute("option")] 
    public Option[] option { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string type { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public bool required { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string label { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string name { get; set; } 
    } 

/// <remarks/> 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
public partial class Option 
{ 
    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string label { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string value { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public bool selected { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlIgnoreAttribute()] 
    public bool selectedSpecified { get; set; } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlTextAttribute()] 
    public string Value { get; set; } 

}