如何为自定义 JsonConverter 设置 FloatParseHandling.Decimal?
How to set FloatParseHandling.Decimal for custom JsonConverter?
如何为自定义 JsonConverter 设置 FloatParseHandling.Decimal?
我们有一个结构 DecimalDbValue,它在内部只包含一个小数字段,我希望它的所有类型都是 de/serialized。
它使用幻数 (decimal.MinValue) 来指示 "null" 值。它是在 .net 2.0 之前创建的,具有可为 null 的值类型!
这是我们的 struct::
的简化版本
[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
?还有其他办法吗?
实际上我想让它 serialize/deserialized 完全像 decimal?
(可为 null 的十进制)
谢谢
好像不可能。
因此我完全删除了 JsonConverter。
在结构上设置此属性:
[JsonObject(MemberSerialization.OptIn)]
以及构造函数中的这个:
[JsonConstructor]
public DecimalDbValue(
decimal? init) //IMPORTANT: if you change the name of init - rename the JsonProperty below too - you might break all existing json out there thou!
还有这个就搞定了属性:
[JsonProperty("init")]
public Decimal Value
{
get
{
return _decValue;
}
}
不幸的是,这会使 json:
膨胀
{
"init": 79228162514264337593543950335.0
}
如果有帮助,您可以为整个 JsonSerializer 设置它:
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
FloatParseHandling = FloatParseHandling.Decimal
};
_innerSerializer = Newtonsoft.Json.JsonSerializer.CreateDefault(settings);
您可能还想看看 FloatFormatHandling
来处理您的可空值。
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_FloatFormatHandling.htm
如何为自定义 JsonConverter 设置 FloatParseHandling.Decimal?
我们有一个结构 DecimalDbValue,它在内部只包含一个小数字段,我希望它的所有类型都是 de/serialized。
它使用幻数 (decimal.MinValue) 来指示 "null" 值。它是在 .net 2.0 之前创建的,具有可为 null 的值类型!
这是我们的 struct::
的简化版本 [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
?还有其他办法吗?
实际上我想让它 serialize/deserialized 完全像 decimal?
(可为 null 的十进制)
谢谢
好像不可能。
因此我完全删除了 JsonConverter。
在结构上设置此属性:
[JsonObject(MemberSerialization.OptIn)]
以及构造函数中的这个:
[JsonConstructor]
public DecimalDbValue(
decimal? init) //IMPORTANT: if you change the name of init - rename the JsonProperty below too - you might break all existing json out there thou!
还有这个就搞定了属性:
[JsonProperty("init")]
public Decimal Value
{
get
{
return _decValue;
}
}
不幸的是,这会使 json:
膨胀{
"init": 79228162514264337593543950335.0
}
如果有帮助,您可以为整个 JsonSerializer 设置它:
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
FloatParseHandling = FloatParseHandling.Decimal
};
_innerSerializer = Newtonsoft.Json.JsonSerializer.CreateDefault(settings);
您可能还想看看 FloatFormatHandling
来处理您的可空值。
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_FloatFormatHandling.htm