web-dev-qa-db-ja.com

C#およびnewtonsoftでのJSONの日付と日付のシリアル化

一部のプロパティがyyyy-MM-ddThh:mm:ss.000Zの形式のDateTime(ミリ秒は3桁である必要があり、そうでない場合はエンドポイントで検証に失敗する)で定義されるAPIにJSONを送信しています時間)プロパティ。

私はこのようなフォーマッターを使用するという多くのメッセージを見てきました:

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 onlyタイプをどのように扱いますか?常に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\"}"
14
DomBat

コメントで述べたように、JSONには標準の日付表現はありません。 ISO8601はde-facto標準です。つまり、ほとんどの人は数年前にこれを使用し始めました。 ISO8601ではnotミリ秒が必要です。他のエンドポイントがそれらを必要とする場合、事実上の標準に違反しています。

Json.NETは、バージョン4.5以降のIOS8601を使用します。現在のバージョンは10.0.3です。次のコード:

JsonConvert.SerializeObject(DateTime.Now)

返却値

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

私のマシンで。タイムゾーンオフセットに注意してください。それも標準の一部です。 ZはUTCを意味します。

can正しい形式であれば、独自の時刻形式を指定します。この場合、yyyy-MM-ddTH:mm:ss.fffZである必要があります。ミリ秒の場合はfffおよび24時間の場合はHHに注意してください。

次のコード

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

返却値

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

フォーマット文字列はnotを実行し、タイムゾーン変換を強制します。 DateTimeZoneHandling設定を使用して、Json.NETに時刻を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"

UPDATE

Matt Johnsonが説明しているように、Zは単なるリテラルであり、KZ設定に応じて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のdefault動作です。

最後に、.NETにはDate- onlyタイプはありませんyet。 DateTimeは、日付と日付と時刻の両方の値に使用されます。 DateTime.Date プロパティを使用して、DateTimeの日付部分を取得できます。 DateTime.Today で現在の日付を取得できます。

時刻はTimespanタイプで表されます。 DateTime.TimeOfDay を使用して、DateTime値から時刻を抽出できます。 Timespanstrictlyではなく、24時間以上を表すことができる時刻型です。

それは何でしたかまだ

明示的な日付のサポートであるTimeOfDayは、 CoreFX Labプロジェクト から始まります。これには、UTF8サポート、日付、文字列、チャネルなど、.NETランタイムに表示される可能性が高いextremelyの「実験的」機能が含まれています。これらのいくつかは、すでに個別のNuGetパッケージとして表示されます。

System.Time クラスを既に使用できます。コードをコピーするか、実験的なNuGetソースを介して追加します。

22

現在の協定世界時から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;
}