让 NodaTime.Serialization.JsonNet 使用自定义日期格式

The*_*heQ 1 c# json json.net deserialization nodatime

我正在尝试反序列化 JSON,其中包含格式为 的日期2017-10-26 13:32:11 Etc/GMT当与Json.NETNodaTime.Serialization.JsonNet结合使用时, NodaTime似乎支持这一点。我在 StackOverflow 上找到了一些信息,这些信息使我仅使用 NodaTime 就能完成这项工作:

var date = "2017-10-26 13:32:11 Etc/GMT";

var pattern = ZonedDateTimePattern.CreateWithInvariantCulture(
    "yyyy'-'MM'-'dd HH':'mm':'ss z", 
    DateTimeZoneProviders.Tzdb
);

var result = pattern.Parse(date);
Run Code Online (Sandbox Code Playgroud)

但是,当将此示例扩展为使用其他两个包反序列化 JSON 时,我无法让它工作。通过阅读文档和其他资源,我相信这应该有效:

public class DateObj
{
    public ZonedDateTime Date { get; set; }
}

void Main()
{
    var date = "2017-10-26 13:32:11 Etc/GMT";
    var json = $"{{\"Date\": \"{date}\"}}";

    var pattern = ZonedDateTimePattern.CreateWithInvariantCulture(
        "yyyy-MM-dd HH:mm:ss z",
        DateTimeZoneProviders.Serialization
    );

    var settings = new JsonSerializerSettings();
    settings.ConfigureForNodaTime(pattern.ZoneProvider);
    var dateObj = JsonConvert.DeserializeObject<DateObj>(json, settings);
}
Run Code Online (Sandbox Code Playgroud)

但它在最后一行抛出异常,表示The value string does not match a quoted string in the pattern. Value being parsed: '2017-10-26^ 13:32:11 Etc/GMT'. (^ indicates error position.). 我究竟做错了什么?

Jon*_*eet 5

目前,您正在创建一个特定的ZonedDateTime模式 - 但实际上您并没有在任何地方告诉 Json.NET 该模式。

如果这是您需要使用的唯一Noda Time 类型,我建议您ConfigureForNodaTime根本不要调用 - 因为这会使用ZonedDateTime错误的模式配置转换器。我们有NodaTime.Serialization.JsonNet 的内部代码来替换转换器,但目前尚未公开。(也许我们应该这样做......)

不过,创建一个转换器并为其配置设置很简单:

var settings = new JsonSerializerSettings
{
    DateParseHandling = DateParseHandling.None,
    Converters = { new NodaPatternConverter<ZonedDateTime>(pattern) }
};
Run Code Online (Sandbox Code Playgroud)

这是完整程序中的样子。请注意,鉴于您肯定有 TZDB 标识符,我DateTimeZoneProviders.Tzdb在这里明确使用,而不是:DateTimeZoneProviders.Serialization

using Newtonsoft.Json;
using NodaTime;
using NodaTime.Serialization.JsonNet;
using NodaTime.Text;
using System;

public class DateObj
{
    public ZonedDateTime Date { get; set; }
}

class Program
{
    static void Main()
    {
        var date = "2017-10-26 13:32:11 Etc/GMT";
        var json = $"{{\"Date\": \"{date}\"}}";

        var pattern = ZonedDateTimePattern.CreateWithInvariantCulture(
            "yyyy-MM-dd HH:mm:ss z",
            DateTimeZoneProviders.Tzdb
        );

        var settings = new JsonSerializerSettings
        {
            DateParseHandling = DateParseHandling.None,
            Converters = { new NodaPatternConverter<ZonedDateTime>(pattern) }
        };
        var dateObj = JsonConvert.DeserializeObject<DateObj>(json, settings);
        Console.WriteLine(dateObj.Date);
    }
}
Run Code Online (Sandbox Code Playgroud)