Подтвердить что ты не робот

Десериализация дат с форматом dd/mm/yyyy с использованием Json.Net

Я пытаюсь десериализовать объект из данных JSON в класс С# (я использую Newtonsoft Json.NET): данные содержат даты в строчном значении типа 09/12/2013, где формат dd/mm/yyyy.

Если я вызываю JsonConvert.DeserializeObject<MyObject>(data); даты загружаются в свойство datetimes класса С#, например mm/dd/yyyy, а затем значение даты 12 сентября 2013 года (вместо 9 декабря 2013 года).

Можно ли настроить JsonConvert для получения даты в правильном формате?

4b9b3361

Ответ 1

Вы можете использовать IsoDateTimeConverter и указать DateTimeFormat, чтобы получить нужный результат, например:

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

Демо:

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

Вывод:

day = 9
month = 12
year = 2013

Ответ 2

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

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

Ответ 3

Вы также можете настроить его в JsonSerializer:

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

Ответ 4

Поддержка нескольких форматов:

Это то, что я использую:

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

тогда вы сделаете это:

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

а затем десериализовать, используя любой обычный способ, который вы делали раньше...

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

альтернатива

Другой путь был бы таким же, как сказал @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

Также я просто пишу это, Custom DateTime Converter, который будет соответствовать вашему обычному формату или календарю

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

Замечания:

Другие способы, которые вы предоставляете, настраиваются один раз и могут быть более простыми и полезными в большинстве случаев... но здесь, провайдер, предоставляет мне услугу, которая предоставляет даты в двух форматах для каждого объекта, и один из этих объектов предоставляет две даты, каждая в другом календаре... так что полезно знать эти два способа, которые я привожу здесь

Ответ 5

Добавить культуру в WebConfig:

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

Затем добавьте фрагмент кода ниже в файле WebApiConfig.cs

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

jsonFormatter.SerializerSettings = jSettings;

Культура pt-BR работает со стандартным dd-MM-yyyy, если вы не хотите размещать культуру в WebConfig, вы можете создать экземпляр только для этого объекта.

Ответ 6

В моем опыте самым простым и простым решением всегда является добавление свойства string в ваш объект CLR (MyObject) в вашем случае для использования JSON.Net. Также на вашем объекте вы помещаете свойство DateTime, только как получатель, который будет анализировать строку datetime, которую вы десериализовали, используя JSON.Net в ожидаемом формате.

Это позволяет вам использовать десериализатор из коробки и полагаться на хороший ol 'fashioned С#, чтобы выполнить эту работу. Никакой муссы, никакой суеты.

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

Ответ 7

Я не знаю, почему другие ответы не будут работать для меня.... Вот что сработало для меня (я установил это глобально):

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
    DateFormatString = "yyyy'/'MM'/'dd' 'HH':'mm'.'ss"
};

Обратите внимание, "разграничивает разделители.

Ответ 8

Согласно newtonsoft вы можете использовать класс JsonSerializerSettings с

DateFormatString

поле Я также делаю на моих проектах ниже.

string json = @"[
 '7 December, 2009',
 '1 January, 2010',
 10 February, 2010'
]";

IList<DateTime> dateList = JsonConvert.DeserializeObject<IList<DateTime>>(json, new 
JsonSerializerSettings
{
    DateFormatString = "d MMMM, yyyy"
});

foreach (DateTime dateTime in dateList)
{
   Console.WriteLine(dateTime.ToLongDateString());
}
// Monday, 07 December 2009
// Friday, 01 January 2010
// Wednesday, 10 February 2010