将十进制序列化为JSON,如何舍入?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (17)

我有一个类

public class Money
{
    public string Currency { get; set; }
    public decimal Amount { get; set; }
}

并想将其序列化为JSON。如果我使用JavaScriptSerializer我得到

{"Currency":"USD","Amount":100.31000}

由于API我必须符合需求JSON金额最多两位小数,我觉得它应该有可能以某种方式改变JavaScriptSerializer串行化十进制字段的方式,但我不知道如何。还有就是SimpleTypeResolver你可以在构造函数中通过,但它只能在类型,只要我能理解工作。该JavaScriptConverter,可以通过添加RegisterConverters(...)似乎是要进行Dictionary

我想得到

{"Currency":"USD","Amount":100.31}

我序列化后。另外,改为加倍是不可能的。我可能需要做一些舍入(100.311应该变成100.31)。

有谁知道如何做到这一点?有没有其他方法JavaScriptSerializer可以让你更详细地控制序列化?

提问于
用户回答回答于

在第一种情况下000没有伤害,值仍然是相同的,并且将被反序列化为完全相同的值。

在第二种情况下,JavascriptSerializer不会帮助你。的JavacriptSerializer是不应该改变的数据,因为它是序列化到一个公知的格式它不提供在部件级别的数据转换(但它提供了自定义对象转换器)。你想要的是一个转换+序列化,这是一个两阶段的任务。

两点建议:

1)使用DataContractJsonSerializer:添加将值舍入的另一个属性:

public class Money
{
    public string Currency { get; set; }

    [IgnoreDataMember]
    public decimal Amount { get; set; }

    [DataMember(Name = "Amount")]
    public decimal RoundedAmount { get{ return Math.Round(Amount, 2); } }
}

2)克隆舍入值的对象:

public class Money 
{
    public string Currency { get; set; }

    public decimal Amount { get; set; }

    public Money CloneRounding() {
       var obj = (Money)this.MemberwiseClone();
       obj.Amount = Math.Round(obj.Amount, 2);
       return obj;
    }
}

var roundMoney = money.CloneRounding();

我猜json.net也无法做到这一点,但我不是100%确定。

用户回答回答于

到目前为止,我还没有完全满意所有这些技术。JsonConverterAttribute看起来是最有前途的,但我无法忍受每个组合选项的硬编码参数和转换器类的泛滥。

所以,我提交了一个PR,增加了将各种参数传递给JsonConverter和JsonProperty的能力。它已被上游接受,我预计将在下一个版本中发布(无论是6.0.5之后的版本)

你可以这样做:

public class Measurements
{
    [JsonProperty(ItemConverterType = typeof(RoundingJsonConverter))]
    public List<double> Positions { get; set; }

    [JsonProperty(ItemConverterType = typeof(RoundingJsonConverter), ItemConverterParameters = new object[] { 0, MidpointRounding.ToEven })]
    public List<double> Loads { get; set; }

    [JsonConverter(typeof(RoundingJsonConverter), 4)]
    public double Gain { get; set; }
}

有关示例,请参阅CustomDoubleRounding()测试。

扫码关注云+社区