【发布时间】:2020-01-07 09:17:28
【问题描述】:
如何为自定义 JsonConverter 设置 FloatParseHandling.Decimal?
我们有一个结构 DecimalDbValue,它在内部只保存一个十进制字段,我想对其所有类型进行反序列化。
它使用一个幻数(decimal.MinValue)来表示一个“空”值。它是在 .net 2.0 之前创建的,具有可为空的值类型!
这是我们结构体的简化版本::
[Serializable]
[JsonConverter(typeof(DecimalDbValueJsonConverter))]
public struct DecimalDbValue : ISerializable
{
private readonly Decimal _decValue;
public DecimalDbValue(
decimal init)
{
_decValue = init;
}
[JsonConstructor]
public DecimalDbValue(
decimal? init)
{
if (init.HasValue)
_decValue = init.Value;
else
_decValue = decimal.MinValue;
}
private DecimalDbValue(
SerializationInfo objSerializationInfo,
StreamingContext objStreamingContext)
{
_decValue = objSerializationInfo.GetDecimal("value");
}
public bool IsNotNull
{
get
{
return !IsNull;
}
}
public bool IsNull
{
get
{
return _decValue.Equals(Decimal.MinValue);
}
}
public Decimal Value
{
get
{
return _decValue;
}
}
public void GetObjectData(
SerializationInfo info,
StreamingContext context)
{
info.AddValue("value", _decValue);
}
}
我创建了一个 JsonConverter:
class DecimalDbValueJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(DecimalDbValue) == objectType;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var value = reader.Value == null ? (decimal?)null : Convert.ToDecimal(reader.Value);
return new DecimalDbValue(value);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var dbValue = (DecimalDbValue)value;
if (dbValue.IsNull)
writer.WriteNull();
else
writer.WriteValue(dbValue.Value);
}
}
并在 DecimalDbValue 结构上设置属性 [JsonConverter(typeof(DecimalDbValueJsonConverter))]
我添加了一个测试:
[Test]
public void TestMaxDecimalDbValue()
{
var s = new DecimalDbValue(decimal.MaxValue);
var json = JsonConvert.SerializeObject(s, Formatting.Indented);
var x = JsonConvert.DeserializeObject<DecimalDbValue>(json);
Assert.AreEqual(s, x);
}
但它会抛出:
System.OverflowException : Value was either too large or too small for a Decimal.
如何为 JsonConverter 设置 FloatParseHandling.Decimal?如何使它也适用于MaxValue?有没有其他办法?
实际上我想让它像decimal?(可为空的十进制)一样序列化/反序列化
谢谢
【问题讨论】:
-
哪一行导致异常?请分享堆栈跟踪和
DecimalDbValue类。另外,您使用的是哪个 .NET 版本? -
本帖中的回答应该可以帮助您解决问题Force decimal type in class definition during serialization
-
@PavelAnikhouski Convert.ToDecimal(reader.Value); ReadJson 内导致异常。我们正在使用 .net 4.7.2。我不能发布整个结构,它非常冗长。在
ReadJson内的Convert.ToDecimal(reader.Value)上抛出异常当尝试其他解决方案时serializer.Populate(reader, existingValue);抛出Newtonsoft.Json.JsonSerializationException : Unexpected initial token 'Float' when populating object. Expected JSON object or array. Path '', line 1, position 31. -
请将此信息添加到您的问题中。如果没有
DecimalDbValue属性、IsNull和Value,我至少无法重现您的问题 -
@toebens - 如果
DecimalDbValue是根对象 那么FloatParseHandlingConverter将不起作用,因为它需要应用于容器类型。将其应用于DecimalDbValue本身将不起作用,因为在调用ReadJson()时,十进制值已经作为double读入。在这种情况下,您需要显式设置JsonSerializerSettings.FloatParseHandling。但是当不是根对象时,将FloatParseHandlingConverter应用于容器将起作用。见dotnetfiddle.net/BmgKYj。你真的用DecimalDbValue作为你的根吗?
标签: c# .net json.net jsonconverter