作为对第二个问题的替代答案(假设您不想费心编译自己的Json.NET源自定义版本),您可以创建自己的自定义JsonConverter类来处理十进制、浮点和双精度值。以下是我使用的版本:
class DecimalJsonConverter : JsonConverter
{
public DecimalJsonConverter()
{
}
public override bool CanRead
{
get
{
return false;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
}
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(decimal) || objectType == typeof(float) || objectType == typeof(double));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (DecimalJsonConverter.IsWholeValue(value))
{
writer.WriteRawValue(JsonConvert.ToString(Convert.ToInt64(value)));
}
else
{
writer.WriteRawValue(JsonConvert.ToString(value));
}
}
private static bool IsWholeValue(object value)
{
if (value is decimal decimalValue)
{
int precision = (Decimal.GetBits(decimalValue)[3] >> 16) & 0x000000FF;
return precision == 0;
}
else if (value is float floatValue)
{
return floatValue == Math.Truncate(floatValue);
}
else if (value is double doubleValue)
{
return doubleValue == Math.Truncate(doubleValue);
}
return false;
}
}
这将保留 decimal 类型的值的精度。如果您愿意忽略 decimal 值的精度,可以使 IsWholeValue() 函数的小数部分与 float/double 部分相同:
private static bool IsWholeValue(object value)
{
if (value is decimal decimalValue)
{
return decimalValue == Math.Truncate(decimalValue);
}
else if (value is float floatValue)
{
return floatValue == Math.Truncate(floatValue);
}
else if (value is double doubleValue)
{
return doubleValue == Math.Truncate(doubleValue);
}
return false;
}
在任何一种情况下,要使用上面的代码,只需像这样调用序列化器:
string json = JsonConvert.SerializeObject(value, new DecimalJsonConverter())