JToken 不像 JsonConvert.DeserializeObject 那样反序列化

JToken does not deserialise like JsonConvert.DeserializeObject

我 运行 在使用 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 的默认行为是将示例中的时间日期字符串解析为 DateTimeNodaPatternConverter 需要 string,而不是 DateTime。 您可以改用 JToken.Load 方法并传递 DateParseHandling 设置为 DateParseHandling.None

JSonTextReader

当您使用 JsonConvert.DeserializeObject 时,它会使用您在 jsonOptions 中创建的 JsonSerializerSettingsConfigureForNodaTime 方法将 DateParseHandling 属性 设置为 DateParseHandling.None,这就是为什么 JsonConvert.DeserializeObject 在您传递您所做的设置时起作用的原因。