C # & Newtonsoft 中的 JSON 日期和时间序列化



我们正在将 JSON 发送到由 swagger 定义的 API,该 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# 如何处理仅日期类型?它似乎总是序列化为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}-dd-ddTdd:dd:dd.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}-dd-dd$")]
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毫秒HH24 小时。

以下代码

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 将时间视为本地或 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根据DateTimeZoneHandling设置生成Z或偏移量。

格式字符串与 DateTimeZoneHandling.Utcyyyy-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.Date 属性获取 DateTime 的日期部分。您可以使用 DateTime.Today 检索当前日期。

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

那还是什么

对显式日期、时间的支持正在通过 CoreFX Lab 项目提供。这包含有可能出现在 .NET 运行时中的"实验性"功能,如 UTF8 支持、日期、字符串、Channles。其中一些已显示为单独的 NuGet 包。

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

获取当前通用时间到 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;
}

如果像Willie Esteche一样,您希望转换一个太低的数字,那么您可能已经得到了一个Unix日期时间值。 他的解决方案确实有效,但是从.Net Framework 4.6开始,有一种更简单的方法来做事。

给定值 1500013000,首先使用 FromUnixTimeSeconds() 方法将其转换为 DateTimeOffset ,然后只需获取 DateTime 组件即可。

DateTime dt = DateTimeOffset.FromUnixTimeSeconds(1500013000).UtcDateTime;

转换回来(假设UTC)是这样执行的:

long Udt = new DateTimeOffset(dt,TimeSpan.Zero).ToUnixTimeSeconds();

就我而言,我在 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

你可以试试这个:

DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");

相关内容

  • 没有找到相关文章

最新更新