我要求从 RavenDB 检索的十进制值具有与存储时相同的格式。 示例属性值 33
数据库中存储的序列化 json 存储的值恰好为 33,这与预期一致。但反序列化时,我在 Decimal 属性中得到值 33.0。
我尝试使用自定义 JsonConverter 只是为了检查反序列化时发生的情况
public class DecimalFormatConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(decimal);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return Convert.ToDecimal(reader.Value);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue((decimal)value);
}
}
在ReadJson中,检查reader.Value
时,它是33.0(应该是33)。我无法在这里实现舍入或自定义格式,因为如果该值存储为 33.0 或 33.00,则加载时必须保持完全相同的格式。 我已经定了
serializer.FloatParseHandling = Newtonsoft.Json.FloatParseHandling.Decimal;
尽管这在本例中可能不相关。
这有几个含义,但基本上意味着您需要使用正确的格式将数据写入输出格式。
您需要使用
FloatParseHandling = FloatParseHandling.Decimal
和以下转换器:
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteRawValue(value.ToString());
}
请注意,我们将小数值作为字符串
写入输出,不使用引号。
解析时,FloatParseHandling.Decimal
会将其读取为十进制,其余就可以了。
另请参阅:
https://ravendb.net/docs/article-page/5.4/csharp/server/kb/numbers-in-ravendbhttps://ravendb.net/docs/article-page/5.4/csharp/client-api/configuration/serialization#numbers-deserialization
if (reader.TokenType == JsonToken.String)
{
string value = (string)reader.Value;
if (decimal.TryParse(value, out decimal result))
return result;
}
else if (reader.TokenType == JsonToken.Float)
{
// Preserve the exact format
return decimal.Parse(reader.Value.ToString(),
CultureInfo.InvariantCulture);
}
如果代码以不同的文化小数格式运行(例如小数分隔符 . 或 ,取决于文化),它会弄乱小数。
到目前为止我找到的最好的解决方案是:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null)
return null;
return Convert.ToDecimal(reader.Value, CultureInfo.InvariantCulture);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(Convert.ToDecimal(value).ToString(CultureInfo.InvariantCulture));
}