Newtonsoft反序列化Json错误
我遇到过一个例子,Newtonsoft获取完全有效的JSON文本,但反序列化错误。我有一个包含嵌入类的对象,该类由成员Year、Month、Week和DayOfWk组成。JSON如下所示:Newtonsoft反序列化Json错误,json,f#,json.net,Json,F#,Json.net,我遇到过一个例子,Newtonsoft获取完全有效的JSON文本,但反序列化错误。我有一个包含嵌入类的对象,该类由成员Year、Month、Week和DayOfWk组成。JSON如下所示: "openDate": { "Year": 1997, "Month": 12, "Week": 5, "DayOfWk": 5 }, 但反序列化后返回的数据是Year=1、Month=1、Week=1和DayOfWk=1,而不管输入的是什么JSON 下面是代码(用F#表示,但应易于阅读
"openDate": {
"Year": 1997,
"Month": 12,
"Week": 5,
"DayOfWk": 5
},
但反序列化后返回的数据是Year=1、Month=1、Week=1和DayOfWk=1,而不管输入的是什么JSON
下面是代码(用F#表示,但应易于阅读):
TradeDate是一个有问题的类——它是一个F#类,公开属性Year、Month、Week和DayOfWk。年、月和周是整数;DayOfWeek是DayOfWeek枚举。DailyAnalysis对象中的所有其他字段都返回了正确的值
如何解决这个问题
请注意,如果在反序列化对象调用中不包含该类型,它确实会获得正确的数据,但只是将其作为对象返回,并且转换为正确的类型非常困难(即,我不知道如何在F#中执行)
有人能指出我忽略的一些明显的(甚至是模糊的)东西吗,或者给我指出其他资源吗
更新:请注意,
TradeDate
的构造函数使用一个DateTime
参数。假设您的TradeDate
是不可变的(通常在f#中发生),那么Json.NET可以通过找到一个参数化的构造函数来反序列化此类类型,然后通过按名称(modulo case)将构造函数参数与JSON属性匹配来调用它。将为不匹配的参数指定默认值。如果TradeDate
实际将一个DateTime
作为输入,您将获得所看到的行为
例如,如果我们采用这样的简化版本:
type TradeDate(date : DateTime) =
member this.Year = date.Year
member this.Month = date.Month
member this.DayOfMonth = date.Day
然后使用Json.NET对其进行双向访问,如下所示:
let t1 = new TradeDate(new DateTime(1997, 12, 25))
let json1 = JsonConvert.SerializeObject(t1)
let t2 = JsonConvert.DeserializeObject<TradeDate>(json1)
let json2 = JsonConvert.SerializeObject(t2)
printfn "\nResult after round-trip:\n%s" json2
let converter = new TradeDateConverter()
let t2 = JsonConvert.DeserializeObject<TradeDate>(json1, converter)
这正是你所看到的。演示小提琴#1
那么,你有什么选择?首先,您可以修改TradeDate
以拥有必要的构造函数,并用标记标记它。只要应用了属性,它就可以是私有的:
type TradeDate [<JsonConstructor>] private(year : int, month : int, dayOfMonth: int) =
member this.Year = year
member this.Month = month
member this.DayOfMonth = dayOfMonth
new(date : DateTime) = new TradeDate(date.Year, date.Month, date.Day)
并反序列化如下:
let t1 = new TradeDate(new DateTime(1997, 12, 25))
let json1 = JsonConvert.SerializeObject(t1)
let t2 = JsonConvert.DeserializeObject<TradeDate>(json1)
let json2 = JsonConvert.SerializeObject(t2)
printfn "\nResult after round-trip:\n%s" json2
let converter = new TradeDateConverter()
let t2 = JsonConvert.DeserializeObject<TradeDate>(json1, converter)
let converter=new TradeDateConverter()
让t2=JsonConvert.DeserializeObject(json1,转换器)
演示小提琴#3
注:
交易日期
的代码,特别是在日期时间
和年/月/周/周表示之间转换的代码。结果证明这有点不寻常,所以我没有把它包括在答案中;请参阅和,了解如何执行此操作假设您的
TradeDate
是不可变的(通常在f#中发生),那么Json.NET能够通过查找一个参数化的构造函数来反序列化此类类型,然后通过按名称(模数大小写)将构造函数参数与Json属性匹配来调用它。将为不匹配的参数指定默认值。如果TradeDate
实际将一个DateTime
作为输入,您将获得所看到的行为
例如,如果我们采用这样的简化版本:
type TradeDate(date : DateTime) =
member this.Year = date.Year
member this.Month = date.Month
member this.DayOfMonth = date.Day
然后使用Json.NET对其进行双向访问,如下所示:
let t1 = new TradeDate(new DateTime(1997, 12, 25))
let json1 = JsonConvert.SerializeObject(t1)
let t2 = JsonConvert.DeserializeObject<TradeDate>(json1)
let json2 = JsonConvert.SerializeObject(t2)
printfn "\nResult after round-trip:\n%s" json2
let converter = new TradeDateConverter()
let t2 = JsonConvert.DeserializeObject<TradeDate>(json1, converter)
这正是你所看到的。演示小提琴#1
那么,你有什么选择?首先,您可以修改TradeDate
以拥有必要的构造函数,并用标记标记它。只要应用了属性,它就可以是私有的:
type TradeDate [<JsonConstructor>] private(year : int, month : int, dayOfMonth: int) =
member this.Year = year
member this.Month = month
member this.DayOfMonth = dayOfMonth
new(date : DateTime) = new TradeDate(date.Year, date.Month, date.Day)
并反序列化如下:
let t1 = new TradeDate(new DateTime(1997, 12, 25))
let json1 = JsonConvert.SerializeObject(t1)
let t2 = JsonConvert.DeserializeObject<TradeDate>(json1)
let json2 = JsonConvert.SerializeObject(t2)
printfn "\nResult after round-trip:\n%s" json2
let converter = new TradeDateConverter()
let t2 = JsonConvert.DeserializeObject<TradeDate>(json1, converter)
let converter=new TradeDateConverter()
让t2=JsonConvert.DeserializeObject(json1,转换器)
演示小提琴#3
注:
交易日期
的代码,特别是在日期时间
和年/月/周/周表示之间转换的代码。结果证明这有点不寻常,所以我没有把它包括在答案中;请参阅和,了解如何执行此操作您可以共享
TradeDate
类型吗?即a?不能用简单的示例重现,请看,我所能猜测的是TradeDate
构造函数的参数名称与属性名称不匹配。Json.NET使用参数名称将构造函数参数与属性匹配,因此如果名称不一致,则会传入默认值。看见但是如果没有一个我们只能猜测.dbc-我想你的最后一点可能是答案-构造函数需要一个日期时间图,当然,Json无论如何都不需要知道这是什么。我将探索其他方法来构建它。谢谢。我现在没有时间检查,但这可能是一个迫不及待的评估问题吗?将letJsonText=…
更改为letJsonText()=…
您可以共享TradeDate
类型吗?即a?不能用简单的示例重现,请看我能猜到的是TradeDate
构造函数的参数名称与属性名称不匹配。Json.NET使用参数名称将构造函数参数与属性匹配,因此如果名称不一致,则会传入默认值。看见但是如果没有一个我们只能猜测.dbc-我想你的最后一点可能是答案-构造函数需要一个日期时间图,当然,Json无论如何都不需要知道这是什么。我将探索其他方法来构建它。谢谢。我现在没有时间检查,但这可能是一个迫不及待的评估问题吗?将letJsonText=…
更改为letJsonText()=…