代码之家  ›  专栏  ›  技术社区  ›  Ben Griswold

禁止XmlSerializer发出空值类型

  •  63
  • Ben Griswold  · 技术社区  · 17 年前

    请考虑下面的金额值类型属性,该属性被标记为可空XMLNET:

    [XmlElement(IsNullable=true)] 
    public double? Amount { get ; set ; }
    

    <amount xsi:nil="true" />
    

    我希望XmlSerializer完全抑制该元素,而不是发出该元素。为什么?我们正在使用Authorize.NET进行在线支付,如果存在此空元素,Authorize.NET将拒绝请求。

    当前的解决方案/解决方法是根本不序列化Amount value类型属性。相反,我们创建了一个互补属性SerializableMount,它基于Amount并被序列化。由于SerializableMount是String类型,与引用类型类似,如果默认为null,则XmlSerializer会抑制这些类型,因此一切都很正常。

    /// <summary>
    /// Gets or sets the amount.
    /// </summary>
    [XmlIgnore]
    public double? Amount { get; set; }
    
    /// <summary>
    /// Gets or sets the amount for serialization purposes only.
    /// This had to be done because setting value types to null 
    /// does not prevent them from being included when a class 
    /// is being serialized.  When a nullable value type is set 
    /// to null, such as with the Amount property, the result 
    /// looks like: &gt;amount xsi:nil="true" /&lt; which will 
    /// cause the Authorize.NET to reject the request.  Strings 
    /// when set to null will be removed as they are a 
    /// reference type.
    /// </summary>
    [XmlElement("amount", IsNullable = false)]
    public string SerializableAmount
    {
        get { return this.Amount == null ? null : this.Amount.ToString(); }
        set { this.Amount = Convert.ToDouble(value); }
    }
    

    3 回复  |  直到 17 年前
        1
  •  137
  •   Marc Gravell    17 年前

    尝试添加:

    public bool ShouldSerializeAmount() {
       return Amount != null;
    }
    

    框架的某些部分可以识别许多模式。欲知详情, XmlSerializer 也找 public bool AmountSpecified {get;set;} .

    完整示例(也切换到 decimal ):

    using System;
    using System.Xml.Serialization;
    
    public class Data {
        public decimal? Amount { get; set; }
        public bool ShouldSerializeAmount() {
            return Amount != null;
        }
        static void Main() {
            Data d = new Data();
            XmlSerializer ser = new XmlSerializer(d.GetType());
            ser.Serialize(Console.Out, d);
            Console.WriteLine();
            Console.WriteLine();
            d.Amount = 123.45M;
            ser.Serialize(Console.Out, d);
        }
    }
    

    更多有关 ShouldSerialize* on MSDN

        2
  •  6
  •   mko    12 年前

    还有另一种选择

     <amount /> instead of <amount xsi:nil="true" />
    

    使用

    [XmlElement("amount", IsNullable = false)]
    public string SerializableAmount
    {
        get { return this.Amount == null ? "" : this.Amount.ToString(); }
        set { this.Amount = Convert.ToDouble(value); }
    }
    
        3
  •  -1
  •   Nicolas Battaglia    9 年前

    您可以尝试以下方法:

    xml.Replace("xsi:nil=\"true\"", string.Empty);