gpt4 book ai didi

c# - 反序列化自定义数据类型实现 IConvertible 的问题

转载 作者:行者123 更新时间:2023-11-30 21:31:05 27 4
gpt4 key购买 nike

我有一个类 ChargesDetail 并且正在尝试反序列化 json,如下所示。这里我使用的数据类型是 Amount

public class ChargesDetail
{
public double DiscountRate { get; set; }
public Amount DiscountAmount { get; set; }
}

public class Amount:IConvertible
{
private double _val = 0;
private int _decimal = 5;

public Amount()
{
}

public Amount(double amount): this()
{
// this.Value = amount;
_val = Math.Round(amount, _decimal);
}

#region IConvertible Members

// Implementation snipped

#endregion
}

我的 JSON 看起来像:

{ "DiscountRate":0.0, "DiscountAmount":0.0 }

我正在尝试像这样反序列化:

T result = JsonConvert.DeserializeObject<ChargesDetail>(json);

它给了我一个异常(exception):

Invalid cast from 'System.Double' to 'Amount'.

at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) at System.Double.System.IConvertible.ToType(Type type, IFormatProvider provider) at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)

如何将 json 反序列化为这种自定义数据类型?

  • 我无法删除 IConvertible,因为它会在某些计算中抛出 System.StackOverflowException。
  • 我无法将金额类型更改为 double 类型,因为在“金额”类中有超过 100 个相同类型的属性正在计算。

最佳答案

正如您的问题表明您正在使用 ,您可以使用 custom JsonConverter 将您的 Amount 序列化为单个十进制值:

public class AmountConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Amount);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Would decimal be more appropriate than double?
var value = serializer.Deserialize<double?>(reader);
if (value == null)
return null;
return new Amount(value.Value);

}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(((Amount)value).Value);
}
}

然后您可以按如下方式将其应用于您的模型:

[JsonConverter(typeof(AmountConverter))]
public class Amount : IConvertible
{
private double _val = 0;
private int _decimal = 5;

public double Value { get { return _val; } }

public Amount()
{

}

public Amount(double amount)
: this()
{
// this.Value = amount;
_val = Math.Round(amount, _decimal);
}

#region IConvertible Members
#endregion
}

或者在JsonSerializerSettings.Converters中添加序列化和反序列化时:

var settings = new JsonSerializerSettings
{
Converters = { new AmountConverter() },
};
var = JsonConvert.DeserializeObject<T>(json, settings);

注意事项:

  1. 如果 Amount 旨在表示货币数量,您可能会考虑从 double 切换到 decimal

    但如果这样做,则需要切换到 FloatParseHandling.Decimal在某个更高级别,以防止在 JsonTextReader 解析期间丢失精度。这可以做到,例如通过设置 JsonSerializerSettings.FloatParseHandling全局或通过从 this answer 中获取 FloatParseHandlingConverter Force decimal type in class definition during serialization 并将其应用于父类 ChargesDetail,如下所示:

    [JsonConverter(typeof(FloatParseHandlingConverter), FloatParseHandling.Decimal)]
    public class ChargesDetail
    {
    public decimal DiscountRate { get; set; }
    public Amount DiscountAmount { get; set; }
    }

演示 fiddle here .

关于c# - 反序列化自定义数据类型实现 IConvertible 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53755988/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com