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

时间:2017-09-08 15:41:30

标签: c# json date datetime json.net

我们正在向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\"}"

4 个答案:

答案 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