一尘不染

C#和Newtonsoft中的JSON Date和DateTime序列化

json

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

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

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类型?它似乎总是序列化为DateTime.MinValue()

这是一个例子:

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

这是招摇的生成类

 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\"}"

阅读 1085

收藏
2020-07-27

共1个答案

一尘不染

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

从4.5版开始,Json.NET使用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

yyyy-MM-ddTH:mm:ss.fffKDateTimeZoneHandling.Utc 的格式字符串:

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的日期部分。您可以使用DateTime.Today检索当前日期。
__

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

那是什么

对显式Date,TimeOfDay的支持正在通过CoreFX
Lab项目进行
。它包含“实验”功能,这些功能 有可能出现在.NET
Runtime中,例如UTF8支持,日期,字符串,卷轴。其中一些已经显示为单独的NuGet软件包。

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

2020-07-27