JSON以相同的方式序列化两个十进制数字
Posted
技术标签:
【中文标题】JSON以相同的方式序列化两个十进制数字【英文标题】:JSON Serialize two decimal numbers the same way 【发布时间】:2013-08-12 16:39:13 【问题描述】:如何强制 NewtonSoft Json 序列化器以相同的方式序列化两个小数?
decimal a = 1234.1200M;
decimal b = 1234.12M;
var sa = JsonConvert.SerializeObject(new value = a );
var sb = JsonConvert.SerializeObject(new value = b);
Console.WriteLine(sa);
Console.WriteLine(sb);
结果是: “价值”:1234.1200 “价值”:1234.12
如何强制它用 4 位小数对它们进行序列化,以便结果相同?
【问题讨论】:
有点小技巧,删除M
之前的尾随零。很高兴在这里见到你 +1
【参考方案1】:
您可以按如下方式格式化小数:
var sa = JsonConvert.SerializeObject(new value = a.ToString("#.#000") );
var sb = JsonConvert.SerializeObject(new value = b.ToString("#.#000") );
【讨论】:
但这是一个字符串而不是小数。您的结果将是"value": "1234.1200"
。此外,当小数是更复杂对象的一部分时,这不起作用,而不仅仅是我在示例中使用的简单版本。
如果您想将其视为小数,“1234.1200”和“1234.12”之间没有任何区别。您要求的是字符串表示形式的差异。有人可以说,你是在让它像小数一样走路,像弦一样嘎嘎……【参考方案2】:
在稍微摆弄一下序列化程序后,我找到了一个“答案”:
private class JsonTextWriterOptimized : JsonTextWriter
public JsonTextWriterOptimized(TextWriter textWriter)
: base(textWriter)
public override void WriteValue(decimal value)
// we really really really want the value to be serialized as "0.0000" not "0.00" or "0.0000"!
value = Math.Round(value, 4);
// divide first to force the appearance of 4 decimals
value = Math.Round((((value+0.00001M)/10000)*10000)-0.00001M, 4);
base.WriteValue(value);
第一个 Math.Round 将在第 4 个之后删除所有小数。 值+0.00001M 完成后,像 100 这样的数字变为 100.00001。然后我们乘除。所有这一切都使小数点坚持到小数点后 4 位。然后我们四舍五入以确保我们通过 +0.00001 添加的第 5 位小数消失了。 这似乎适用于我提出的任何价值观。
然后使用自定义编写器:
var jsonSerializer = Newtonsoft.Json.JsonSerializer.Create();
var sb = new StringBuilder(256);
var sw = new StringWriter(sb, CultureInfo.InvariantCulture);
using (var jsonWriter = new JsonTextWriterOptimized(sw))
jsonWriter.Formatting = Formatting.None;
jsonSerializer.Serialize(jsonWriter, instance);
我还修正了自己的答案(我忘记了类似的问题): Serializing a decimal to JSON, how to round off?
【讨论】:
以上是关于JSON以相同的方式序列化两个十进制数字的主要内容,如果未能解决你的问题,请参考以下文章
使用 DataAnnotation 序列化 JSON 以应用十进制格式规则