本文介绍了c# & 中的 JSON 日期和日期时间序列化牛顿软件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们将 JSON 发送到一个由 swagger 定义的 API,其中一些属性是 DateTime,格式为 yyyy-MM-ddThh:mm:ss.000Z(毫秒必须是 3 位数字,否则在端点验证失败),有些是日期(无时间)属性.

We are sending JSON to an API defined by swagger that some properties are DateTime in the format yyyy-MM-ddThh:mm:ss.000Z (the milliseconds must be 3 digits or it fails validation at the endpoint) and some are Date (no time) properties.

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

I have seen many messages saying use the formatters like this:

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()

but this does not convert the DateTimes into the correct format, and how does C# deal with a Date only type? It always seems to serialise as DateTime.MinValue()

这是一个例子:

有人将 json 作为字符串发送给我,但日期和日期时间格式不正确,要发送到端点.我希望 swagger 类和 json 反序列化会格式化它们,但事实并非如此.

Someone sends me json as string but the the dates and datetimes in the incorrect format to be sent to the endpoint. I was hoping that the swagger class and json deserialisation would format them but it is not.

这是swagger生成的类

This is the swagger generated class

 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 正确,但我做错了或缺少某些东西

So I try and coerce the json to be correct but I'm doing it wrong or something is missing

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 是de-facto 标准,即大多数人几年前就开始使用它.ISO8601 需要毫秒.如果另一个端点需要它们,那就违反了事实上的标准.

As I mentioned in a comment, there is no standard date representation in JSON. The ISO8601 is the de-facto standard, ie most people started using this some years ago. ISO8601 does not require milliseconds. If the other endpoint requires them, it's violating the defacto standard.

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

Json.NET uses IOS8601 since version 4.5. The current one is 10.0.3. The following code :

JsonConvert.SerializeObject(DateTime.Now)

返回

"2017-09-08T19:01:55.714942+03:00"

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

On my machine. Notice the timezone offset. That's also part of the standard. Z means UTC.

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

You can specify your own time format, provided it's the correct one. In this case, it should be yyyy-MM-ddTHH:mm:ss.fffZ. Notice the fff for milliseconds and HH for 24-hour.

以下代码

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 将时间视为 Local 或 Utc:

The format string does not force a timezone translation. You can tell Json.NET to treat the time as Local or Utc through the DateTimeZoneHandling setting :

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"

更新

正如马特约翰逊解释的那样,Z 只是一个文字,而 K 生成 Z 或偏移量,具体取决于 DateTimeZoneHandling 设置.

As Matt Johnson explains, Z is just a literal, while K generates either Z or an offset, depending on the DateTimeZoneHandling setting.

格式字符串 yyyy-MM-ddTH:mm:ss.fffK 与 DateTimeZoneHandling.Utc :

The format string yyyy-MM-ddTH:mm:ss.fffK with 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 的 默认 行为,除了强制的毫秒精度.

Which, by the way is the default behaviour of Json.NET, apart from the forced millisecond precision.

最后,.NET 没有Date-only 类型yet.DateTime 用于日期和日期+时间值.您可以使用 DateTime.Date 属性.您可以使用 DateTime 检索当前日期.今天.

Finally, .NET doesn't have a Date-only type yet. DateTime is used for both dates and date+time values. You can get the date part of a DateTime with the DateTime.Date property. You can retrieve the current date with DateTime.Today.

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

Time of day is represented by the Timespan type. You can extract the time of day from a DateTime value with DateTime.TimeOfDay. Timespan isn't strictly a time-of-day type as it can represent more than 24 hours.

那是什么?

通过 CoreFX 实验室项目支持显式日期和 TimeOfDay.这包含非常可能出现在 .NET 运行时中的实验性"功能,例如 UTF8 支持、日期、字符串、通道.其中一些已经显示为单独的 NuGet 包.

Support for explicit Date, TimeOfDay is comming through the CoreFX Lab project. This contains "experimental" features that are extremely likely to appear in the .NET Runtime like UTF8 support, Date, String, Channles. Some of these already appear as separate NuGet packages.

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

One can use the System.Time classes already, either by copying the code or adding them through the experimental NuGet source

这篇关于c# &amp; 中的 JSON 日期和日期时间序列化牛顿软件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 18:16