我有以下构造函数,一个用于默认值,另一个用于Json Deserialization
public Truck(string maker, string model, int relYear,
int purcYear,bool isSold,int wheels, int miles)
:this(maker,model,relYear,purcYear,wheels,miles)
{
IsSold = isSold;
}
这适用于Json
[JsonConstructor]
public Truck(string maker, string model, int relYear,
int purcYear, int wheels, int miles)
{
if (string.IsNullOrWhiteSpace(maker))
throw new ArgumentException("Manufacture cann't be empty", nameof(maker));
if (string.IsNullOrWhiteSpace(model))
throw new ArgumentException("model cann't be empty", nameof(model));
if (relYear < 0 || purcYear < 0)
throw new ArgumentException("Years are not negative values");
Manufacturer = maker;
Model = model;
PurchaseYear = purcYear;
ReleaseYear = relYear;
Wheels = wheels;
Miles = miles;
}
在我的主要内容中有一个不同Ivehicle
类型的数组。当我序列化第一辆卡车时它工作正常,但是当我反序列化它时,它不起作用并为Exception
抛出IsNullOrWhiteSpace
但此时maker
不为空
我在这里遗漏了某些内容或允许default constructor
调用Jsonconstructor
来调用此问题?
有一件事是当我删除if块string.IsNullOrWhiteSpace(maker)
然后它工作正常而不会抛出异常
var vehls = new IVehicle[]
{
new Truck("Ford", "F15000", 2011, 2016,true,8,23000),
new Truck("Ford", "F-150", 2009, 2014,false,8,13000),
new Car(4,13000,"Ford", "Super Duty")
};
string sl = JsonConvert.SerializeObject(vehls[0],Formatting.Indented);
Console.WriteLine(sl);
var tk = JsonConvert.DeserializeObject<Truck>(sl);
Console.WriteLine(tk.Manufacturer);
答案 0 :(得分:2)
一个问题是您的构造函数参数名称与您的属性名称不匹配。当Json.NET使用非默认构造函数时,它通过执行与大小写无关的字符串匹配将JSON属性名称与构造函数参数匹配。如果未找到匹配项,则会传递默认值,从而触发ReadToEnd();
检查。
因此,您的构造函数需要如下所示:
IsNullOrWhiteSpace()
如果找不到构造函数参数的匹配项,但找到了读/写成员的匹配项,则稍后将设置该成员。这解释了您删除 [JsonConstructor]
public Truck(string manufacturer, string model, int releaseYear,
int purchaseYear, int wheels, int miles)
{
if (string.IsNullOrWhiteSpace(manufacturer))
throw new ArgumentException("Manufacture can't be empty", nameof(manufacturer));
if (string.IsNullOrWhiteSpace(model))
throw new ArgumentException("model can't be empty", nameof(model));
if (releaseYear < 0 || purchaseYear < 0)
throw new ArgumentException("Years are not negative values");
this.Manufacturer = manufacturer;
this.Model = model;
this.PurchaseYear = purchaseYear;
this.ReleaseYear = releaseYear;
this.Wheels = wheels;
this.Miles = miles;
}
支票后代码的原因。
答案 1 :(得分:1)
您在编写和阅读结构时是否指定了TypeNameHandling?通常,当您序列化运行时类型(Car
,Truck
)与编译时间(IVehicle
)不同的内容时,您需要的是什么。这将继承汽车(或者在您的情况下,接口实现问题)。
参见文档:
http://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm