web-dev-qa-db-fra.com

Pouvez-vous dire à JSON.Net de sérialiser DateTime en tant qu'Utc, même si non spécifié?

Les dates dans ma base de données sont stockées en tant que Utc. Mais quand je les récupère avec le cadre d'entité, ils sortent comme type non spécifié.

Lorsque JSON.Net les sérialise, ils ne sont pas au format Utc. Y a-t-il un moyen de dire à JSON.Net de sérialiser DateTimes en tant que Utc même si leur type n'est pas spécifié en tant que Utc?

43
C.J.

Définissez DateTimeZoneHandling sur JsonSerializerSettings à Utc. Cela convertira toutes les dates en UTC avant de les sérialiser.

public void SerializeObjectDateTimeZoneHandling()
{
  string json = JsonConvert.SerializeObject(
    new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Unspecified),
    new JsonSerializerSettings
    {
      DateTimeZoneHandling = DateTimeZoneHandling.Utc
    });

  Assert.AreEqual(@"""2000-01-01T01:01:01Z""", json);
}

Documentation: DateTimeZoneHandling setting

92
James Newton-King

La réponse ci-dessus fonctionne totalement, et j'ai donc utilisé cela pour créer un attribut permettant de convertir une réponse d'API de PST à UTC.

J'ai d'abord dû créer une JsonConverter

public class UTCDateTimeConverter : Newtonsoft.Json.JsonConverter {
    private TimeZoneInfo pacificZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
    public override bool CanConvert(Type objectType) {
        return objectType == typeof(DateTime);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        if (reader.Value == null) return null;
        var pacificTime = DateTime.Parse(reader.Value.ToString());
        return TimeZoneInfo.ConvertTimeToUtc(pacificTime, pacificZone);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        writer.WriteValue(TimeZoneInfo.ConvertTimeFromUtc((DateTime) value, pacificZone));
    }
}

Ensuite, j'ai dû appliquer cela aux propriétés devant être converties.

public class Order{
    [JsonConverter(typeof(UTCDateTimeConverter))]
    public DateTime OrderDate {get;set;}
}
9
JustMaier

Comme @dez mentionné dans un commentaire, vous pouvez "marquer" les objets DateTime comme UTC directement dans le code .net juste après les avoir CHARGÉS à partir de la base de données et AVANT de les sérialiser:

var item = GetItemFromDb(...);

// mark appropriate DateTime fields manually as needed
item.OrderDate = DateTime.SpecifyKind(item.OrderDate, DateTimeKind.Utc);

// now it will be serialized to "2018-10-17T16:21:23.507Z" with the Z at the end
// and javascript will parse it properly and convert to local timezone as needed
0
Ekus