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

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#如何处理仅限日期的类型?它似乎总是按日期时间顺序排列.MinValue()

Here is an example:

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生成的类

 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; }
    }

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

推荐答案

正如我在 comments 中提到的,JSON中没有标准的日期表示.ISO8601是de-facto标准(大多数人几年前开始使用).ISO8601不需要not毫秒.如果另一个端点需要它们,那么它违反了事实标准.

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

JsonConvert.SerializeObject(DateTime.Now)

returns

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

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

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

The following code

var settings=new JsonSerializerSettings{DateFormatString ="yyyy-MM-ddTHH:mm:ss.fffZ"};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);

returns

"2017-09-08T19:04:14.480Z"

格式字符串确实not强制时区转换.您可以通过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);

Returns :

"2017-09-08T16:08:19.290Z"

UPDATE

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

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

Will return :

2017-09-11T9:10:08.293Z

Changing to DateTimeZoneHandling.Utc will return

2017-09-11T12:15:12.862+03:00

顺便说一下,这就是Json的default种行为.NET,除了强制毫秒精度.

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.

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.

What was that yet?

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.

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

Json相关问答推荐

服务器不返回JSON

PowerShell:将Invoke-WebRequest与变量一起使用

Vega Lite中的图例对齐

给定一个包含两个数组的JSON输入文件,如何使用Jolt将一个数组中的每个元素与另一个数组组合在一起?

基于 JSON 字段的 Jolt 条件标志

报告重复的对象键

如何使NiFi将数据库单列中的多个值转化为Solr索引中的数组?

Oracle json 对象的最后一个值不在引号中

如何通过 jolt 将一个对象中的键和值添加到数组中的每个对象中

在 PostgreSQL 中 Select 分层 JSON 作为表

jq:来自嵌套 JSON 的映射

如何将动态复杂 json 解析为dart 对象或模型

PowerShell - JSON/PsCustomObject - 为什么我的数组被扁平化为一个对象?

可以通过 POST 使用 EventSource 传递参数的服务器发送事件 (SSE)

Jackson Json:如何将数组转换为 JsonNode 和 ObjectNode?

使用 jq 从 bash 中管道分隔的键和值创建 JSON

如何使用 SwiftyJSON 将字符串转换为 JSON

我可以使用空字符串作为对象标识符吗?

JSON 和 BSON 哪个更轻量级?

为什么 jqXHR.responseText 返回字符串而不是 JSON 对象?