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

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

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

var jsonSettings = new JsonSerializerSettings(); jsonSettings.DateFormatString = "yyyy-MM-ddThh:mm:ss.000Z"; //try .fffZ too var jsonObject= Newtonsoft.Json.JsonConvert.DeserializeObject(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(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(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-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); 

回报

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

UPDATE

正如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 -only类型。 DateTime用于日期和日期+时间值。 您可以使用DateTime.Date属性获取DateTime的日期部分。 您可以使用DateTime.Today检索当前日期。

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

那是什么?

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

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

获取当前的json日期时间格式的通用时间,反之亦然:

 DateTime currentDateTime = DateTime.Now.ToUniversalTime(); var jsonDateTime = GetJSONFromUserDateTime(currentDateTime); DateTime getDateTime = GetUserDateTimeFromJSON(jsonDateTime); 

以下是两种方法:

 ///  /// Convert UserDateTime({9/7/2018 8:37:20 AM}) to JSON datetime(1536309440373) format ///  ///  ///  public static string GetJSONFromUserDateTime(DateTime givenDateTime) { string jsonDateTime = string.Empty; if (givenDateTime != null) { JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat }; jsonDateTime = JsonConvert.SerializeObject(givenDateTime, microsoftDateFormatSettings); jsonDateTime = jsonDateTime.Replace("\"\\/Date(", "").Replace(")\\/\"", ""); } return jsonDateTime; } ///  /// Convert JSON datetime(1536309440373) to user datetime({9/7/2018 8:37:20 AM}) ///  ///  ///  public static dynamic GetUserDateTimeFromJSON(string jsonDateTime) { dynamic userDateTime = null; if (!string.IsNullOrEmpty(jsonDateTime)) { JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat }; userDateTime = JsonConvert.DeserializeObject("\"\\/Date(" + jsonDateTime + ")\\/\"", microsoftDateFormatSettings); } return userDateTime; }