c#和newtonsoft中的JSON Date和DateTime序列化

Dom*_*Bat 16 c# datetime json date json.net

我们将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);
Run Code Online (Sandbox Code Playgroud)

但这并没有将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; }
    }
Run Code Online (Sandbox Code Playgroud)

所以我试着强迫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\"}"
Run Code Online (Sandbox Code Playgroud)

Pan*_*vos 27

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

Json.NET从4.5版开始使用IOS8601.目前的是10.0.3.以下代码:

JsonConvert.SerializeObject(DateTime.Now)
Run Code Online (Sandbox Code Playgroud)

回报

"2017-09-08T19:01:55.714942+03:00"
Run Code Online (Sandbox Code Playgroud)

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

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

以下代码

var settings=new JsonSerializerSettings{DateFormatString ="yyyy-MM-ddTH:mm:ss.fffZ"};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);
Run Code Online (Sandbox Code Playgroud)

回报

"2017-09-08T19:04:14.480Z"
Run Code Online (Sandbox Code Playgroud)

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

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

退货:

"2017-09-08T16:08:19.290Z"
Run Code Online (Sandbox Code Playgroud)

UPDATE

正如马特约翰逊所解释的那样,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);
Run Code Online (Sandbox Code Playgroud)

将返回 :

2017-09-11T9:10:08.293Z
Run Code Online (Sandbox Code Playgroud)

改变DateTimeZoneHandling.Utc将返回

2017-09-11T12:15:12.862+03:00
Run Code Online (Sandbox Code Playgroud)

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

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

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

那是什么

支持显式日期,TimeOfDay正在通过CoreFX Lab项目.这包含有可能出现在.NET运行时中的"实验性"功能,如UTF8支持,Date,String,Channles.其中一些已经显示为单独的NuGet包.

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