2016-07-28 1 views
5

J'ai des problèmes avec la désérialisation.Désérialise l'élément XML vide en tant que Guid.Empty

<Order> 
    ... 
    <CardNumber /> 
    ... 
</Order> 

Si je

<CardNumber>00000000-0000-0000-0000-000000000000</CardNumber> 

il fonctionne normalement, mais dans le cas où je viens d'utiliser <CardNumber /> - objet n'est pas désérialisation (

Est-il possible de désérialiser élément vide comme Guid. Vide

Propriété qui doit être mappée avec la valeur de cet élément:

[XmlElement(ElementName = "CardNumber")] 
[JsonProperty("CardNumber")] 
public Guid? CardNumber { get; set; } 

Même situation dans JSON fonctionne normalement et utiliser Guid.Empty au lieu de valeur de l'élément vide

{ 
    "CardNumber": "" 
} 
+1

Avez-vous essayé de sérialiser une instance de cette classe en XML et de vérifier le résultat? –

+1

Que voulez-vous dire par * objet n'est pas désérialisant (* .Une exception est levée? Si oui, pouvez-vous [modifier] votre question pour inclure la sortie complète 'ToString()' de l'exception, y compris le message, le type d'exception et une exception interne? – dbc

Répondre

1

L'exception que vous voyez explique clairement le problème:

System.InvalidOperationException occurred 
    Message="There is an error in XML document (3, 3)." 
    InnerException: System.FormatException 
     Message="Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)." 

Comme indiqué, XmlSerializer ne supporte pas désérialisation une chaîne vide à un Guid. Ainsi, vous devez faire la conversion manuellement à l'aide d'une propriété de substitution:

[XmlRoot("Order")] 
public class Order 
{ 
    [XmlIgnore] 
    [JsonProperty("CardNumber")] 
    public Guid? CardNumber { get; set; } 

    [XmlElement(ElementName = "CardNumber", IsNullable = true)] 
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)] 
    [JsonIgnore] 
    public string XmlCardNumber 
    { 
     get 
     { 
      if (CardNumber == null) 
       return null; 
      else if (CardNumber.Value == Guid.Empty) 
       return ""; 
      return XmlConvert.ToString(CardNumber.Value); 
     } 
     set 
     { 
      if (value == null) 
       CardNumber = null; 
      else if (string.IsNullOrEmpty(value)) 
       CardNumber = Guid.Empty; 
      else 
       CardNumber = XmlConvert.ToGuid(value); 
     } 
    } 
} 

Si cela est quelque chose que vous devez faire dans de nombreux types différents qui ont Guid? propriétés, vous pouvez extraire un type de substitution comme ceci:

[XmlType(AnonymousType = true, IncludeInSchema = false)] 
public class XmlGuid 
{ 
    [XmlIgnore] 
    public Guid Guid { get; set; } 

    [XmlText] 
    public string XmlCardNumber 
    { 
     get 
     { 
      if (Guid == Guid.Empty) 
       return null; 
      return XmlConvert.ToString(Guid); 
     } 
     set 
     { 
      if (string.IsNullOrEmpty(value)) 
       Guid = Guid.Empty; 
      else 
       Guid = XmlConvert.ToGuid(value); 
     } 
    } 

    public static implicit operator Guid?(XmlGuid x) 
    { 
     if (x == null) 
      return null; 
     return x.Guid; 

    } 

    public static implicit operator XmlGuid(Guid? g) 
    { 
     if (g == null) 
      return null; 
     return new XmlGuid { Guid = g.Value }; 
    } 

    public static implicit operator Guid(XmlGuid x) 
    { 
     if (x == null) 
      return Guid.Empty; 
     return x.Guid; 

    } 

    public static implicit operator XmlGuid(Guid g) 
    { 
     return new XmlGuid { Guid = g }; 
    } 
} 

Et l'utiliser comme:

[XmlRoot("Order")] 
public class Order 
{ 
    [XmlElement(Type = typeof(XmlGuid), ElementName = "CardNumber", IsNullable = true)] 
    [JsonProperty("CardNumber")] 
    public Guid? CardNumber { get; set; } 
} 

ici je profite du fait que la propriété automatiquement XmlElementAttribute.Type ramasse le implicit conversion J'ai défini pour Guid? de et à XmlGuid.

+0

Merci pour l'explication détaillée! – ashpakov

3

nul n'est pas la même chose que Guid.Empty. Dans le sérialiseur JSON, vous notez null en utilisant une chaîne vide.

Si vous sérialisez votre classe en utilisant XmlSerializer, vous verrez qu'elle utilise xsi:nil="true" pour indiquer une valeur nulle.

Par exemple:

<Order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <CardNumber xsi:nil="true" /> 
</Order> 
+0

Merci beaucoup! – ashpakov