将空 XML 元素反序列化为 Guid.Empty

Posted

技术标签:

【中文标题】将空 XML 元素反序列化为 Guid.Empty【英文标题】:Deserialize empty XML element as Guid.Empty 【发布时间】:2016-12-02 14:34:56 【问题描述】:

我在反序列化方面遇到了一些麻烦。

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

如果我使用

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

它工作正常,但如果我只使用&lt;CardNumber /&gt; - 对象没有反序列化(

有没有办法将空元素反序列化为 Guid.Empty?

应该与该元素的值映射的属性:

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

JSON 中的相同情况正常工作并使用 Guid.Empty 代替空元素值


    "CardNumber": ""

【问题讨论】:

您是否尝试过将该类的实例序列化为 XML 并检查结果? 你的意思是 object is not deserializing (. 是否抛出异常?如果是这样,你能edit你的问题包括完整的ToString()输出吗?异常包括消息、异常类型和任何内部异常? 【参考方案1】:

您看到的异常清楚地解释了问题:

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

如上所述,XmlSerializer 不支持将空字符串反序列化为 Guid。因此,您需要使用代理属性手动进行转换:

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

如果这是您需要在具有Guid? 属性的许多不同类型中执行的操作,您可以像这样提取代理类型:

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

并像这样使用它:

[XmlRoot("Order")]
public class Order

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

在这里,我利用XmlElementAttribute.Type 属性自动获取我为Guid? 定义的implicit conversion 和XmlGuid 的事实。

【讨论】:

感谢详细解释!【参考方案2】:

Null 与Guid.Empty 不同。在 JSON 序列化程序中,您使用空字符串表示 null。

如果您使用XmlSerializer 序列化您的类,您会看到它使用xsi:nil="true" 来表示空值。

例如:

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

【讨论】:

以上是关于将空 XML 元素反序列化为 Guid.Empty的主要内容,如果未能解决你的问题,请参考以下文章

将空 JSON 数组反序列化为空 TreeMap

Java Jackson将空字段反序列化为POJO中的默认空列表

当元素可能是许多可能元素之一时,将 XML 元素反序列化为对象

将子XML元素反序列化为XML字符串

Jackson xml反序列化 - 序列化为一个列表,其中包含任意元素

如何将 xml 元素值反序列化为 C# 类属性