web-dev-qa-db-fra.com

Désérialisation des dates au format jj / mm / aaaa à l'aide de Json.Net

J'essaie de désérialiser un objet des données JSON vers une classe C # (j'utilise Newtonsoft Json.NET): les données contiennent des dates dans une valeur de chaîne comme 09/12/2013 Où le format est dd/mm/yyyy.

Si j'appelle JsonConvert.DeserializeObject<MyObject>(data); les dates sont chargées sur la propriété datetimes de la classe C # comme mm/dd/yyyy, Puis la valeur de la date est le 12 septembre 2013 (au lieu du 9 décembre 2013).

Est-il possible de configurer JsonConvert pour obtenir la date au format correct?

36
girtri

Vous pouvez utiliser un IsoDateTimeConverter et spécifier le DateTimeFormat pour obtenir le résultat souhaité, par exemple:

MyObject obj = JsonConvert.DeserializeObject<MyObject>(jsonString, 
                   new IsoDateTimeConverter { DateTimeFormat = "dd/MM/yyyy" });

Démo:

class Program
{
    static void Main(string[] args)
    {
        string json = @"{ ""Date"" : ""09/12/2013"" }";

        MyObject obj = JsonConvert.DeserializeObject<MyObject>(json, 
            new IsoDateTimeConverter { DateTimeFormat = "dd/MM/yyyy" });

        DateTime date = obj.Date;
        Console.WriteLine("day = " + date.Day);
        Console.WriteLine("month = " + date.Month);
        Console.WriteLine("year = " + date.Year);
    }
}

class MyObject
{
    public DateTime Date { get; set; }
}

Sortie:

day = 9
month = 12
year = 2013
45
Brian Rogers
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

var dateTimeConverter = new IsoDateTimeConverter { DateTimeFormat = "dd/MM/yyyy" };
myObject obj = JsonConvert.DeserializeObject<myObject>(myJSONString, dateTimeConverter);
7
Foy

Vous pouvez également le configurer dans JsonSerializer:

var serializer = new JsonSerializer
{
    DateFormatString = "dd/MM/yyyy"
};
6

Prise en charge multi formats:

C'est ce que j'utilise:

public class CustomDateTimeConverter : IsoDateTimeConverter
{
    public CustomDateTimeConverter()
    {
        base.DateTimeFormat = "dd/MM/yyyy";
    }
}

alors vous ferez ceci:

public class MyObject
{
    [JsonConverter(typeof(CustomDateTimeConverter))]
    public DateTime Date {get;set;}
}

puis désérialiser en utilisant comme vous le faisiez avant ...

MyObject obj = JsonConvert.DeserializeObject<MyObject>(json);

Alternative

L'autre façon serait la même que celle de @pimbrouwers:

public class MyObject
{
    [JsonProperty("Date")] //Naturally Case Sensetive
    private string dateJson {get;set;}
    // it would be good to look at @pimbrouwers answer and use nullable
    [JsonIgnore]
    public DateTime Date
    {
        get
        {
            return DateTime.ParseExact(dateJson,"dd/MM/yyyy",CultureInfo.InvariantCulture);
        }
        set
        {
            dateJson = value.ToString("dd/MM/yyyy");
        }
    }

}

DateTimeConverter personnalisé

Aussi, je viens d'écrire ceci, un convertisseur DateTime personnalisé qui correspondrait à votre format ou calendrier personnalisé hors de portée

public class CustomDateTimeConverterJalali : DateTimeConverterBase
{
    //I had no use for WriteJson section, i just wrote it, so i do not guarantee it working
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value == null)
        {
            writer.WriteNull();
            return;
        }

        var nullableType = Nullable.GetUnderlyingType(value.GetType());
        var isNullable = nullableType != null;

        DateTime date;
        if (isNullable)
            date = ((DateTime?) value).Value;
        else
            date = (DateTime) value;


        PersianCalendar pc = new PersianCalendar();

        writer.WriteValue(pc.GetYear(date) + "/" + pc.GetMonth(date) + "/" + pc.GetDayOfMonth(date));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        //this should likely be null, but since the provider json returned empty string, it was unavoidable... (i'm not sure what we will read using reader, if data is actually null on the json side, feel free to experiment 
        if (string.IsNullOrWhiteSpace((string) reader.Value))
        {
            return null;
        }

        var strDate = reader.Value.ToString();

        PersianCalendar pc = new PersianCalendar();
        var dateParts = strDate.Split('/');

        DateTime date = pc.ToDateTime(int.Parse(dateParts[0]), int.Parse(dateParts[1]), int.Parse(dateParts[2]),
            0, 0, 0, 0);

        return date;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);//DateTime=>true | DateTime?=>true
    }
}

Remarque:

Les autres moyens que vous fournissez sont configurés une seule fois et peuvent être plus simples et peuvent être utiles la plupart du temps, mais ici, le fournisseur, fournissez-moi un service, qui fournit des dates en deux formats dans chaque objet, et l'un de ces objets fournit deux dates chacune dans un calendrier différent ... il est donc bon de savoir ces deux façons que je fournis ici

4
deadManN

Ajoutez de la culture dans WebConfig:

<system.web>
   <globalization culture="pt-BR" uiCulture="pt-BR" enableClientBasedCulture="true"/>
</system.web>

Ajoutez ensuite l'extrait de code ci-dessous dans le WebApiConfig.cs fichier

var jsonFormatter =  GlobalConfiguration.Configuration.Formatters.JsonFormatter;
JsonSerializerSettings jSettings = new JsonSerializerSettings()
{
   Culture = System.Globalization.CultureInfo.CurrentCulture
};

jsonFormatter.SerializerSettings = jSettings;

La culture pt-BR fonctionne avec la valeur par défaut dd-MM-yyyy, si vous ne souhaitez pas mettre la culture dans WebConfig, vous pouvez créer une instance uniquement pour cet objet.

2
Fco Junior

D'après mon expérience, la solution la plus simple et la plus simple consiste toujours à ajouter une propriété string sur votre objet CLR (MyObject) dans votre cas pour que JSON.Net l'utilise. Également sur votre objet, vous placez une propriété DateTime, en tant que getter uniquement, qui analysera la chaîne datetime que vous avez désérialisée à l'aide de JSON.Net au format que vous attendez.

Cela vous permet d'utiliser le désérialiseur hors de la boîte et de compter sur un bon vieux c # façonné pour faire le travail. Pas de bruit, pas de bruit.

public class MyObject
{
    public string dtStr { get; set; }
    public DateTime? dt
    {
        get
        {
            DateTime? d = null;

            if (!string.IsNullOrWhiteSpace(dtStr) && DateTime.TryParseExact(dtStr, "dd/mm/yyyy", CultureInfo.InvariantCultureDateTimeStyles.None, out d)
            {
                return d;
            }

            return d;
        }
    }
}
0
pim