我遇到了用JToken反序列化NodaTime.Instant的麻烦。
使用JsonConvert.DeserializeObject时,不会出现此问题。
以下示例代码失败,但有一个例外:
let jsonOptions =
let n = new JsonSerializerSettings()
n.ConfigureForNodaTime(NodaTime.DateTimeZoneProviders.Tzdb)
JToken.Parse("\"2010-02-12T23:22:00Z\"")
.ToObject<Instant>(JsonSerializer.Create(jsonOptions));
异常的堆栈跟踪为:
deserialisation/deserialisation with JToken: Exception: NodaTime.Utility.InvalidNodaDataException: Unexpected token parsing Instant. Expected String, got Date.
at NodaTime.Serialization.JsonNet.NodaPatternConverter`1.ReadJsonImpl(JsonReader reader, JsonSerializer serializer)
at NodaTime.Serialization.JsonNet.NodaConverterBase`1.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer)
at Newtonsoft.Json.Linq.JToken.ToObject[T](JsonSerializer jsonSerializer)
使用
JsonConvert.DeserializeObject
反序列化相同的字符串有效。JsonConvert.DeserializeObject<Instant>("\"2010-02-12T23:22:00Z\"", jsonOptions)
在这里可以找到2个测试:
Tests.fsx
关于什么导致异常的任何想法?
最佳答案
JToken.Parse
在内部使用JSonTextReader
解析字符串。JSonTextReader
的默认行为是将示例中的timedate字符串解析为DateTime
。NodaPatternConverter
需要一个string
,而不是DateTime
。
您可以改用JToken.Load
方法,并传递一个DateParseHandling设置为JSonTextReader
的DateParseHandling.None
。
使用JsonConvert.DeserializeObject
时,请使用在JsonSerializerSettings
中创建的jsonOptions
。ConfigureForNodaTime
方法将DateParseHandling
属性设置为DateParseHandling.None
,这就是为什么当您传递所做的设置时JsonConvert.DeserializeObject
可以工作的原因。