即使传递的参数不为空,JsonConstructor也会抛出异常

时间:2017-03-19 20:45:34

标签: c# json.net

我有以下构造函数,一个用于默认值,另一个用于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);

2 个答案:

答案 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?通常,当您序列化运行时类型(CarTruck)与编译时间(IVehicle)不同的内容时,您需要的是什么。这将继承汽车(或者在您的情况下,接口实现问题)。

参见文档:

http://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm