我有一个类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);
这给了我一个异常,例如:
来自“ System.Double”的无效转换 到“金额”。
at System.Convert.DefaultToType(IConvertible value,Type targetType,IFormatProvider提供程序) System.Double.System.IConvertible.ToType(类型类型,IFormatProvider 提供程序),位于System.Convert.ChangeType(对象值,类型) conversionType,IFormatProvider提供程序)位于 Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader 读者,对象值,CultureInfo文化,JsonContract合同,类型 targetType)
如何将json反序列化为此自定义数据类型?
答案 0 :(得分:2)
由于您的问题表明您正在使用json.net,因此可以使用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);
注意:
如果Amount
旨在表示货币数量,则可以考虑从decimal
切换到double
。
但是,如果这样做,则需要在更高的级别上切换到FloatParseHandling.Decimal
,以防止在JsonTextReader
进行解析的过程中失去精度。这可以例如完成通过全局设置JsonSerializerSettings.FloatParseHandling
或从this answer到{em> Force decimal type in class definition during serialization 抓取FloatParseHandlingConverter
并将其应用于父类ChargesDetail
,如下所示:
[JsonConverter(typeof(FloatParseHandlingConverter), FloatParseHandling.Decimal)]
public class ChargesDetail
{
public decimal DiscountRate { get; set; }
public Amount DiscountAmount { get; set; }
}
演示小提琴here。
答案 1 :(得分:0)
您的类Amount
未实现接口IConvertable
。
答案 2 :(得分:0)
在检查JSON时。
{ "FileVersion":"11.03", "ChargesDetail":{ "DiscountRate":0.0, "DiscountAmount":0.0 } }
public class ChargesDetail
{
public double DiscountRate { get; set; }
public Amount DiscountAmount { get; set; }
}
public class Amount:IConvertible
{
}
在这里您需要将DiscountAmount的类型更改为double,因为您要映射的结构不正确。
或者如果您将JSON更改为
{ "FileVersion":"11.03", "ChargesDetail":{ "DiscountRate":0.0, "DiscountAmount":{ "DiscountAmountVar":0.0 }} }
并分类为
public class ChargesDetail
{
public double DiscountRate { get; set; }
public Amount DiscountAmount { get; set; }
}
public class Amount:IConvertible
{
public double DiscountAmountVar{get;set;}
}
然后您之前的映射将起作用。
答案 3 :(得分:0)
在您的课程金额上,您可以删除// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync("YourProvider", userIdClaim.Value, isPersistent: false, bypassTwoFactor: true);
if (result.Succeeded)
{
_logger.LogInformation("User logged in with {Name} provider.", "YourProvider");
// delete temporary cookie used during external authentication
await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
return RedirectToLocal(returnUrl);
}
if (result.IsLockedOut)
{
return RedirectToAction(nameof(Lockout));
}
else
{
// If the user does not have an account, then ask the user to create an account.
ViewData["ReturnUrl"] = returnUrl;
ViewData["LoginProvider"] = "YourProvider";
var email = claims.FirstOrDefault(x => x.Type == ClaimTypes.Upn).Value;
return View("ExternalLogin", new ExternalLoginViewModel { Email = email });
}
并仅实现为:
IConvertible
通过本课程和您的其他课程:
public class Amount {
public decimal DiscountAmountVar { get; set; }
}
此JSON:**** EDIT ****
public class ChargesDetail
{
public decimal DiscountRate { get; set; }
public Amount DiscountAmount { get; set; }
}
**编辑:刚刚意识到您需要删除Json的一个级别。
您应该能够制作JsonConvert。
主要代码:
string json =
@"{""DiscountRate"":12.0, ""DiscountAmount"":{ ""DiscountAmountVar"":13.0 } }";