I ran into trouble deserialising a NodaTime.Instant with JToken. When using JsonConvert.DeserializeObject the issue does not show up.
The following sample code fails with an exception:
let jsonOptions =
let n = new JsonSerializerSettings()
n.ConfigureForNodaTime(NodaTime.DateTimeZoneProviders.Tzdb)
JToken.Parse("\"2010-02-12T23:22:00Z\"")
.ToObject<Instant>(JsonSerializer.Create(jsonOptions));
The stacktrace of the exception is:
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)
Using JsonConvert.DeserializeObject to deserialize the same string works.
JsonConvert.DeserializeObject<Instant>("\"2010-02-12T23:22:00Z\"", jsonOptions)
2 tests can be found here:
Tests.fsx
Any ideas on what is causing the exception?
JToken.Parse internally use a JSonTextReader to parse the string.
The default behavior of the JSonTextReader is to parse a timedate string as in the sample to a DateTime.
The NodaPatternConverter expects a string, not a DateTime.
You could use the JToken.Load method instead and pass a JSonTextReader that has the DateParseHandling set to DateParseHandling.None
When you are using the JsonConvert.DeserializeObject it use the JsonSerializerSettings you create in jsonOptions.
The ConfigureForNodaTime method set the DateParseHandling property to DateParseHandling.None and this is why JsonConvert.DeserializeObject works when you pass the settings that you do.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With