2016-07-28 24 views
5

Mam pewne problemy z deserializacją.Deserializuj pusty element XML jako Guid.Empty

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

Jeśli używam

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

to działa normalnie, ale w przypadku, gdy używam tylko <CardNumber /> - obiekt nie jest deserializacji (

Czy istnieje jakiś sposób, aby deserializowania pusty element jako GUID. Pusty?

Właściwość, która powinna być odwzorowana na wartość tego elementu:

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

samej sytuacji w JSON pracuje normalnie i używać Guid.Empty zamiast pustej wartości elementu

{ 
    "CardNumber": "" 
} 
+1

Czy próbowałeś serializować instancję tej klasy do XML i sprawdzanie wyniku? –

+1

Co masz na myśli przez * obiekt nie przekształca się w postać szeregową (*. Czy wyjątek został zgłoszony? Jeśli tak, czy możesz [edytować] swoje pytanie, aby dołączyć pełne wyjście "ToString()" wyjątku, w tym komunikat, typ wyjątku i każdy wyjątek wewnętrzny? – dbc

Odpowiedz

1

Wyjątkiem widzisz wyraźnie wyjaśnia problem:

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)." 

Jak stwierdzono, XmlSerializer nie obsługuje deserializacji pusty ciąg do Guid. Tak więc trzeba będzie zrobić konwersję ręcznie przy użyciu właściwości zastępczego:

[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); 
     } 
    } 
} 

Jeśli jest to coś trzeba zrobić w wielu różnych typów, które mają Guid? właściwości, można wyodrębnić rodzaj zastępczej tak:

[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 }; 
    } 
} 

i używać go lubię:

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

Oto jestem automatycznie, korzystając z faktu, że nieruchomość XmlElementAttribute.Type odbiera implicit conversion I zdefiniowany dla Guid? od i do XmlGuid.

+0

Dzięki za szczegółowe wyjaśnienie! – ashpakov

3

Null nie jest taki sam jak Guid.Empty. W serializatorze JSON oznaczasz null, używając pustego łańcucha.

Jeśli serializujesz klasę przy użyciu XmlSerializer, zobaczysz, że używa ona xsi:nil="true" do oznaczenia wartości pustej.

Na przykład:

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

Dziękuję bardzo! – ashpakov