c# - c# 和 newtonsoft 中的 JSON 日期和日期时间序列化

标签 c# json date datetime json.net

我们将 JSON 发送到由 swagger 定义的 API,其中一些属性是格式为 yyyy-MM-ddThh:mm:ss.000Z 的 DateTime(毫秒必须是 3 位数字,否则在端点验证失败)还有一些是日期(无时间)属性。

我看到很多消息说使用这样的格式化程序:

var jsonSettings = new JsonSerializerSettings();
jsonSettings.DateFormatString = "yyyy-MM-ddThh:mm:ss.000Z"; //try .fffZ too
var jsonObject= Newtonsoft.Json.JsonConvert.DeserializeObject<OurSwaggerObject>(json , setting);

但这不会将 DateTimes 转换为正确的格式,C# 如何处理 Date only 类型?它似乎总是序列化为 DateTime.MinValue()

这是一个例子:

有人将 json 作为字符串发送给我,但发送到端点的格式不正确的日期和日期时间。我希望 swagger 类和 json 反序列化可以格式化它们,但事实并非如此。

这是swagger生成的类

 public class OurSwaggerObject
    {
        [Newtonsoft.Json.JsonProperty("dateTimeField", Required = Newtonsoft.Json.Required.Always)]
        [System.ComponentModel.DataAnnotations.Required]
        [System.ComponentModel.DataAnnotations.RegularExpression(@"^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z$")]
        public DateTime dateTimeField { get; set; }

        [Newtonsoft.Json.JsonProperty("dateField", Required = Newtonsoft.Json.Required.Always)]
        [System.ComponentModel.DataAnnotations.Required]
        [System.ComponentModel.DataAnnotations.RegularExpression(@"^\d{4}-\d\d-\d\d$")]
        public DateTime dateField { get; set; }
    }

所以我尝试强制 json 是正确的,但我做错了或缺少某些东西

string json = @"{ 'dateTimeField': '1995-04-07T00:00:00',
                          'dateField': '1995-04-07T00:00:00'
                           }";

        /* The json we need to satisfy the swagger endpoint is:

          { 'dateTimeField': '1995-04-07T00:00:00.000Z',
            'dateField': '1995-04-07'
                           }              
          */

        OurSwaggerObject deserialisedIntoObject = Newtonsoft.Json.JsonConvert.DeserializeObject<OurSwaggerObject>(json);

        string serialisedToString = Newtonsoft.Json.JsonConvert.SerializeObject(deserialisedIntoObject);
        //serialisedToString= "{\"dateTimeField\":\"1995-04-07T00:00:00\",\"dateField\":\"1995-04-07T00:00:00\"}"

        var jsonSettings = new JsonSerializerSettings();
        jsonSettings.DateFormatString = "yyyy-MM-ddThh:mm:ss.fffZ"; //this won't help much for the 'date' only field!
        deserialisedIntoObject = Newtonsoft.Json.JsonConvert.DeserializeObject<OurSwaggerObject>(json,jsonSettings);
        serialisedToString = Newtonsoft.Json.JsonConvert.SerializeObject(deserialisedIntoObject, jsonSettings);
        //serialisedToString="{\"dateTimeField\":\"1995-04-07T00:00:00\",\"dateField\":\"1995-04-07T00:00:00\"}"

最佳答案

正如我在评论中提到的,JSON 中没有标准的日期表示。 ISO8601 是事实上的 标准,即大多数人几年前就开始使用它。 ISO8601 需要毫秒。如果另一个端点需要它们,那就违反了事实上的标准。

Json.NET 从 4.5 版本开始就一直在使用 IOS8601。当前版本是 10.0.3。以下代码:

JsonConvert.SerializeObject(DateTime.Now)

返回

"2017-09-08T19:01:55.714942+03:00"

在我的机器上。注意时区偏移量。这也是标准的一部分。 Z 表示 UTC。

可以指定您自己的时间格式,前提是它是正确的。在这种情况下,它应该是 yyyy-MM-ddTHH:mm:ss.fffZ。注意 fff 代表毫秒 HH 代表 24 小时。

下面的代码

var settings=new JsonSerializerSettings{DateFormatString ="yyyy-MM-ddTHH:mm:ss.fffZ"};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);

返回

"2017-09-08T19:04:14.480Z"

格式字符串强制进行时区转换。您可以通过 DateTimeZoneHandling 设置告诉 Json.NET 将时间视为 Local 或 Utc:

var settings=new JsonSerializerSettings{
                              DateFormatString ="yyyy-MM-ddTH:mm:ss.fffZ",
                              DateTimeZoneHandling=DateTimeZoneHandling.Utc};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);

返回:

"2017-09-08T16:08:19.290Z"

更新

正如 Matt Johnson 解释的那样,Z 只是一个文字,而 K 生成 Z 或偏移量,具体取决于 DateTimeZoneHandling 设置。

带有 DateTimeZoneHandling.Utc 的格式字符串 yyyy-MM-ddTH:mm:ss.fffK :

var settings=new JsonSerializerSettings{
                              DateFormatString ="yyyy-MM-ddTH:mm:ss.fffK",
                              DateTimeZoneHandling=DateTimeZoneHandling.Utc};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);

将返回:

2017-09-11T9:10:08.293Z

更改为 DateTimeZoneHandling.Utc 将返回

2017-09-11T12:15:12.862+03:00

顺便说一句,除了强制的毫秒精度之外,这是 Json.NET 的默认行为。

最后,.NET 还没有 Date 类型,。 DateTime 用于日期和日期+时间值。您可以使用 DateTime.Date 获取 DateTime 的日期部分属性(property)。您可以使用 DateTime.Today 检索当前日期.

一天中的时间由 Timespan 类型表示。您可以使用 DateTime.TimeOfDay 从 DateTime 值中提取一天中的时间. Timespan 不是严格时间类型,因为它可以表示超过 24 小时。

那是什么

支持显式日期,TimeOfDay 正在通过 CoreFX Lab project 提供.这包含“实验性”功能,这些功能极有可能出现在 .NET 运行时中,例如 UTF8 支持、日期、字符串、 channel 。其中一些已作为单独的 NuGet 包出现。

可以使用 System.Time类,通过复制代码或通过实验性 NuGet 源添加它们

关于c# - c# 和 newtonsoft 中的 JSON 日期和日期时间序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46120116/

相关文章:

php - 如何从日期找到一个月的最后一天?

c# - 如何在不迭代所有元素的情况下找到预排序数组中的元素?

c# - MVC 和 Entity Framework Html.DisplayNameFor 与复合 ViewModel

java - 用 Jackson 解析 : throwing exception when format is unexpected

c# - ASP .NET Webhook 接收器

c# - 调用 WCF 引用类型变量

javascript - Date.toLocaleDateString 格式问题

excel - 将日期格式更改为 yyyy-mm-dd

c# - XML反序列化泛型方法

c# - WPF 按钮中的图像在运行时不可见