Deserialize empty XML element as Guid.Empty

后端 未结 2 752
猫巷女王i
猫巷女王i 2021-01-18 19:47

I have some troubles with deserializing.


    ...
    
    ...

If I use

&l         


        
相关标签:
2条回答
  • 2021-01-18 20:01

    Null is not the same as Guid.Empty. In the JSON serializer, you denote null using an empty string.

    If you serialize your class using XmlSerializer you'll see it uses xsi:nil="true" to denote a null value.

    For example:

    <Order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
           xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <CardNumber xsi:nil="true" />
    </Order>
    
    0 讨论(0)
  • 2021-01-18 20:10

    The exception you are seeing explains the problem clearly:

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

    As stated, XmlSerializer does not support deserializing an empty string to a Guid. Thus you will need to do the conversion manually using a surrogate property:

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

    If this is something you need to do in many different types that have Guid? properties, you can extract a surrogate type like so:

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

    And use it like:

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

    Here I am taking advantage of the fact that the XmlElementAttribute.Type property automatically picks up the implicit conversion I defined for Guid? from and to XmlGuid.

    0 讨论(0)
提交回复
热议问题