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

问题描述 投票:0回答:5

我们将 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 反序列化能够格式化它们,但事实并非如此。

这是 swagger 生成的类

 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\"}"
c# json date datetime json.net
5个回答
98
投票

正如我在评论中提到的,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
代表毫秒,
 
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"

格式字符串
强制进行时区转换。您可以通过

Local 设置告诉 Json.NET 将时间视为 Utc

DateTimeZoneHandling
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.fffK

DateTimeZoneHandling.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 小时。
那是什么

支持明确的日期,TimeOfDay

正在通过

CoreFX Lab项目

实现。其中包含“实验性”功能,这些功能“极有可能”出现在 .NET 运行时中,例如 UTF8 支持、日期、字符串、通道。其中一些已经作为单独的 NuGet 包出现。
人们已经可以使用 System.Time 类,可以通过复制代码或通过实验性 NuGet 源添加它们

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

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

3
投票
这两种方法:

/// <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 组件。

1
投票
DateTime dt = DateTimeOffset.FromUnixTimeSeconds(1500013000).UtcDateTime;

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

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

你可以试试这个:
DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");

1
投票

就我而言,我在 vb.net 中使用此配置,它很容易转换为 c #
settings.NullValueHandling = NullValueHandling.Ignore
settings.DateTimeZoneHandling = DateTimeZoneHandling.Local
BE = JsonConvert.DeserializeObject(Of EN_BE)(str, settings)

0
投票
我从 laravel API 获取此格式的日期

2020-08-02T01:41:05.000000Z
我转换为与数据库相同的正确值

2020-08-01 20:41:05
    

© www.soinside.com 2019 - 2024. All rights reserved.