wake-up-neo.com

JSON Date und DateTime Serialisierung in c # und newtonsoft

Wir senden JSON an eine durch swagger definierte API, dass einige Eigenschaften DateTime im Format yyyy-MM-ddThh: mm: ss.000Z sind (die Millisekunden müssen 3-stellig sein oder die Validierung am Endpunkt fehlschlagen) Zeit) Eigenschaften.

Ich habe viele Nachrichten gesehen, in denen gesagt wird, dass sie die folgenden Formatierer verwenden:

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 werden jedoch nicht in das richtige Format konvertiert, und wie wird in C # ein Date-Typ verwendet? Es scheint immer als DateTime.MinValue () zu serialisieren.

Hier ist ein Beispiel:

Jemand sendet mir json als String, aber die Datums- und Datumsangaben im falschen Format werden an den Endpunkt gesendet. Ich hatte gehofft, dass die Swagger-Klasse und Json-Deserialisierung sie formatieren würden, aber es ist nicht so.

Dies ist die von Swagger generierte Klasse

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

Also versuche ich den Json dazu zu bringen, richtig zu sein, aber ich mache es falsch oder es fehlt etwas

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

Wie ich in einem Kommentar erwähnt habe, gibt es in JSON keine Standarddarstellung von Datumsangaben. Die ISO8601 ist der de-facto Standard, dh die meisten Leute haben vor einigen Jahren damit begonnen. ISO8601 erfordert nicht Millisekunden. Wenn der andere Endpunkt dies erfordert, verstößt er gegen den Defacto-Standard.

Json.NET verwendet IOS8601 seit Version 4.5. Die aktuelle Version ist 10.0.3. Der folgende Code:

JsonConvert.SerializeObject(DateTime.Now)

kehrt zurück

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

Auf meiner Maschine. Beachten Sie den Zeitzonenversatz. Das gehört auch zum Standard. Z bedeutet UTC.

Sie können can Ihr eigenes Zeitformat angeben, sofern es das richtige ist. In diesem Fall sollte es yyyy-MM-ddTH:mm:ss.fffZ Sein. Beachten Sie das fff für Millisekunden und HH für 24 Stunden.

Der folgende Code

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

kehrt zurück

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

Die Formatzeichenfolge bewirkt nicht eine Zeitzonenübersetzung. Sie können Json.NET über die DateTimeZoneHandling-Einstellung anweisen, die Zeit als lokal oder als UTC zu behandeln:

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

Kehrt zurück :

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

[~ # ~] Update [~ # ~]

Wie Matt Johnson erklärt, ist Z nur ein Literal, während K abhängig von der Einstellung Z entweder DateTimeZoneHandling oder einen Offset generiert.

Die Formatzeichenfolge yyyy-MM-ddTH:mm:ss.fffK Mit DateTimeZoneHandling.Utc:

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

Wird zurückkehren :

2017-09-11T9:10:08.293Z

Wenn Sie zu DateTimeZoneHandling.Utc Wechseln, kehren Sie zurück

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

Das ist übrigens das default Verhalten von Json.NET, abgesehen von der erzwungenen Millisekunden-Genauigkeit.

Schließlich hat .NET keinen Date- only-Typ noch. DateTime wird sowohl für Datums- als auch für Datums- und Zeitwerte verwendet. Sie können den Datumsteil einer DateTime mit der Eigenschaft DateTime.Date abrufen. Sie können das aktuelle Datum mit DateTime.Today abrufen.

Die Uhrzeit wird durch den Zeitbereichstyp dargestellt. Sie können die Uhrzeit aus einem DateTime-Wert mit DateTime.TimeOfDay extrahieren. Timespan ist nicht genau genommen ein Typ für die Uhrzeit, da er mehr als 24 Stunden darstellen kann.

Was war das noch?

Unterstützung für explizites Datum, TimeOfDay kommt durch das CoreFX Lab-Projekt . Dies enthält "experimentelle" Funktionen, die extrem wahrscheinlich in der .NET-Laufzeit erscheinen, wie UTF8-Unterstützung, Datum, Zeichenfolge, Kanäle. Einige davon erscheinen bereits als separate NuGet-Pakete.

Die Klassen System.Time können bereits verwendet werden, indem der Code kopiert oder über die experimentelle NuGet-Quelle hinzugefügt wird

22

Holen Sie sich das aktuelle Datumsformat für das JSON-Datum und umgekehrt:

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

Hier sind beide Methoden:

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