【问题标题】:Using Newtonsoft JToken.ToObject<T> to deserializeNodaTime Instant使用 Newtonsoft JToken.ToObject<T> 反序列化NodaTime Instant
【发布时间】:2016-07-20 16:58:54
【问题描述】:

我在整个项目中使用 NodaTime 作为标准 BCL DateTime 类的替代品,效果惊人。

我想完全从我的项目中删除 DateTime。我只在一个地方使用它 - 我反序列化一个包含日期的大型 JSON 文件。这些日期总是 UTC,总是以 ISO 8601 格式指定。

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;

namespace Foo.Parsing
{
public class Parser
{
    JSchema schema;
    JObject jsonObject;

    public Parser(string jsonContent, string schemaString)
    {
        schema = JSchema.Parse(schemaString);
        jsonObject = JObject.Parse(jsonContent);
    }

    public MyObject Parse()
    {
        return jsonObject.ToObject<MyObject>();
    }
}

public class MyObject
{
     [JsonProperty(Required = Required.Always)]
     public DateTime date { get; set; }

     // A lot of other properties here.
}
}

这一切都非常有效,但目前我必须使用 Instant.FromDateTimeUtc(myObject.date); 将 DateTimes 转换为 Instant。在 MyObject 我有 DateTimes,如果我尝试将其更改为 Instant,我会收到以下错误:

Newtonsoft.Json.dll 中的 Newtonsoft.Json.JsonSerializationException' 附加信息:将值 2016/07/07 12:00:00 AM 转换为类型“NodaTime.Instant”时出错。路径“日期”,第 4 行,位置 37

我有什么方法可以将我的 JSON 文件反序列化为强类型 MyObject,而我的日期可以直接反序列化为 Instant 而不必转换 DateTime?

【问题讨论】:

  • 您使用的是NodaTime.Serialization.JsonNet package吗?它有可以帮助解决这个问题的转换器。有关设置的详细信息,请参阅Deserializing Noda Time's LocalDateTime with JSON.NET
  • 谢谢,这让我更进了一步,尽管现在我收到一条错误消息“意外的令牌解析即时。预期的字符串,得到日期。” JObject 如何知道这是一个日期?我注意到当我将 MyObject.date 设置为字符串而不是 Instant/DateTime 时,它​​会以不同的(非 ISO)格式返回,因此 JObject.Parse 中的某些内容似乎将格式识别为日期......跨度>

标签: c# json json.net deserialization nodatime


【解决方案1】:

根据Noda Time User Guide

如果您仍然收到“Unexpected token...”消息,那么您可能已经更改了DateParseHandling 设置。 ConfigureForNodaTime 调用会将其设置为 DateParseHandling.None,并且应该保持这种状态。

请注意,这适用于JsonConvert.SerializeObjectJsonConvert.DeserializeObject 类,因为它们接受JsonSettings 参数,也可以通过JsonConvert.DefaultSettings 设置。 Here is a live demo using this approach.

但是,如果您使用的是JObject API,则会出现一个小问题。 JObject.Parse 无法获取设置参数,默认情况下您不会拥有此阶段所需的 DateParseHandling.None。对此的解决方案涉及使用JsonTextReader,并在in this StackOverflow answer 中进行了很好的描述。

【讨论】:

  • 不,我在反序列化之前调用了配置。我尝试如下添加“DateParseHandling.None”。还是没有骰子:JsonSerializer serializer = new JsonSerializer();serializer.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);serializer.DateParseHandling = DateParseHandling.None;return jsonObject.ToObject&lt;MyObject&gt;(serializer);
  • 查看我的更新答案。我相信最后一部分解决了您当前的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-06
  • 1970-01-01
相关资源
最近更新 更多