我们正在向swagger定义的API发送JSON,其中一些属性是DateTime,格式为yyyy-MM-ddThh:mm:ss.000Z(毫秒必须是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类型?它似乎总是序列化为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\"}"
答案 0 :(得分:20)
正如我在评论中提到的,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"
格式字符串不强制进行时区转换。您可以告诉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);
返回:
"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的日期部分。您可以使用DateTime.Today检索当前日期。
时间由Timespan类型表示。您可以使用DateTime.TimeOfDay从DateTime值中提取时间。 Timespan
并非严格一种时间类型,因为它可能代表超过24小时。
那是什么 ?
支持显式日期,TimeOfDay正在通过CoreFX Lab project。这包含&#34;实验&#34; 极可能出现在.NET运行时中的功能,如UTF8支持,Date,String,Channles。其中一些已经显示为单独的NuGet包。
可以通过复制代码或通过实验性NuGet源添加它们来使用System.Time类
答案 1 :(得分:2)
将当前通用时间转换为json日期时间格式,反之亦然:
DateTime currentDateTime = DateTime.Now.ToUniversalTime();
var jsonDateTime = GetJSONFromUserDateTime(currentDateTime);
DateTime getDateTime = GetUserDateTimeFromJSON(jsonDateTime);
这两种方法都是
/// <summary>
/// Convert UserDateTime({9/7/2018 8:37:20 AM}) to JSON datetime(1536309440373) format
/// </summary>
/// <param name="givenDateTime"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Convert JSON datetime(1536309440373) to user datetime({9/7/2018 8:37:20 AM})
/// </summary>
/// <param name="jsonDateTime"></param>
/// <returns></returns>
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;
}
答案 2 :(得分:1)
如果像Willie Esteche一样希望转换一个太低的数字,则可能有一个Unix Date Time值。他的解决方案确实有效,但是从.Net Framework 4.6开始,有一种更简便的方法。
给出一个值1500013000,首先使用FromUnixTimeSeconds()方法将其转换为DateTimeOffset,然后简单地获取DateTime组件。
DateTime dt = DateTimeOffset.FromUnixTimeSeconds(1500013000).UtcDateTime;
像这样执行反向转换(假设使用UTC):
long Udt = new DateTimeOffset(dt,TimeSpan.Zero).ToUnixTimeSeconds();
答案 3 :(得分:0)
就我而言,我在vb.net中使用此配置,因此很容易转换为c#
settings.NullValueHandling = NullValueHandling.Ignore
settings.DateTimeZoneHandling = DateTimeZoneHandling.Local
BE = JsonConvert.DeserializeObject(Of EN_BE)(str, settings)
我从laravel API获取这种格式日期
2020-08-02T01:41:05.000000Z
我将正确的值转换为与数据库相同的值
2020-08-01 20:41:05