当我使用json.net将小数写到json时,我变得很烦人。有时是1 dp,其他时候是2。
显然,我知道将小数输出到具有一定数量的小数(例如this)的字符串的解决方案,但是我猜想如果没有编写自定义的序列化程序,就无法使用json.net进行控制。
我也知道Math.Round要强制使用 最大 小数位数,这个问题与强制执行最小小数位数有关。
Math.Round
前两个测试表明发生了什么,它保持声明或计算中的原始小数位数。
我发现我可以添加然后减去一小部分,接下来的两个测试都可以正常工作,但是有没有更干净的方法?
[TestFixture] public sealed class DecimalPlaces { public class JsonType { public decimal Value { get; set; } } [Test] public void TwoDp() { var obj = new JsonType { Value = 1.00m }; Assert.AreEqual("{\"Value\":1.00}", JsonConvert.SerializeObject(obj)); } [Test] public void OneDp() { var json = new JsonType { Value = 1.0m }; Assert.AreEqual("{\"Value\":1.0}", JsonConvert.SerializeObject(obj)); } private decimal ForceMinimumDp(decimal p, int minDecimalPlaces) { decimal smallFrac = 1m/((decimal)Math.Pow(10, minDecimalPlaces)); return p + smallFrac - smallFrac; } [Test] public void ForceMinimumTwoDp() { var obj = new JsonType { Value = ForceMinimumDp(1.0m, 2) }; Assert.AreEqual("{\"Value\":1.00}", JsonConvert.SerializeObject(obj)); } [Test] public void ForceMinimumThreeDp() { var obj = new JsonType { Value = ForceMinimumDp(1.0m, 3) }; Assert.AreEqual("{\"Value\":1.000}", JsonConvert.SerializeObject(obj)); } }
您可以使用自定义JSON转换器执行此操作:
class DecimalJsonConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof (decimal); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { writer.WriteRawValue(((decimal) value).ToString("F2", CultureInfo.InvariantCulture)); } }
这是一个非常基本的转换器。您可能需要扩展它以支持其他浮点类型,甚至可能还支持整数类型。
现在实例化序列化器,并将其传递给自定义转换器,如下所示:
var serializer = new JsonSerializer(); serializer.Converters.Add(new DecimalJsonConverter());