As an alternative answer to question 2 (assuming you don't want to go through the hassle of compiling your own custom version of the Json.NET source) you can create your own custom JsonConverter class to handle decimal, float, and double values. Here's the version I'm using:
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)
{
decimal decimalValue = (decimal)value;
int precision = (Decimal.GetBits(decimalValue)[3] >> 16) & 0x000000FF;
return precision == 0;
}
else if (value is float || value is double)
{
double doubleValue = (double)value;
return doubleValue == Math.Truncate(doubleValue);
}
return false;
}
}
This will preserve the precision on values of type decimal. If you would prefer to ignore the precision of decimal values, you can make the decimal portion of the IsWholeValue() function work the same as the float/double portion:
private static bool IsWholeValue(object value)
{
if (value is decimal)
{
decimal decimalValue = (decimal)value;
return decimalValue == Math.Truncate(decimalValue);
}
else if (value is float || value is double)
{
double doubleValue = (double)value;
return doubleValue == Math.Truncate(doubleValue);
}
return false;
}
In either case, to use the above code, just call the serializer like this:
string json = JsonConvert.SerializeObject(value, new DecimalJsonConverter())
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…