【问题标题】:Suppress Null Value Types from Being Emitted by XmlSerializer禁止 XmlSerializer 发出 Null 值类型
【发布时间】:2009-08-18 20:55:56
【问题描述】:

请考虑以下标记为可空 XmlElement 的金额值类型属性:

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

当可空值类型设置为 null 时,C# XmlSerializer 结果如下所示:

<amount xsi:nil="true" />

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

当前的解决方案/解决方法是根本不序列化 Amount 值类型属性。相反,我们创建了一个补充属性 SerializableAmount,它基于 Amount 并被序列化。由于 SerializableAmount 是 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); }
}

当然,这只是一种解决方法。是否有更简洁的方法来抑制发出空值类型元素?

【问题讨论】:

  • 顺便说一句; “金额”(用于付款)可能更适合decimal
  • 优点:浮点货币是邪恶的。
  • @Marc 也感谢您指出这一点。
  • 你的方案不错,我也用。然而,马克的答案更好......

标签: c# xml xml-serialization


【解决方案1】:

尝试添加:

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的信息。

【讨论】:

  • 嗨,Marc,这就是我喜欢这样的原因......你学到了这样的东西。不过我有几个问题。我只能在 msdn 中找到有关此功能的以下文档:msdn.microsoft.com/en-us/library/53b8022e.aspx 你知道任何 real 文档吗?此外,由于此功能的文档记录很差,我会觉得使用它有点脏。使用像这样看似未记录的功能是否“安全”?
  • 哇,这就是我所说的晦涩难懂。不过,很酷,你找到了它。
  • 谢谢马克。既然您告诉我要查找什么,我想我在 XmlSerializer“属性 + 指定”模式上找到了 MSDN 参考。这是:msdn.microsoft.com/en-us/library/…。如果你问我,一旦你找到了正确的 MSDN 参考页面,你甚至很难找到它。 :) 再次感谢。
  • 嗯...我已经看过了,但我找不到更正式的东西...仍在寻找。
  • 这里是 ShouldSerialize 模式的 MSDN 参考:msdn.microsoft.com/en-us/library/53b8022e(VS.71).aspx
【解决方案2】:

还有另一种获取方式

 <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】:

    你可以试试这个:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多