Serializing multiple DateTime properties in the same class using different formats for each one

I have a class with two DateTime properties. I need to serialize each of the properties with a different format. How can I do it? I tried:

JsonConvert.SerializeObject(obj, Formatting.None,
      new IsoDateTimeConverter {DateTimeFormat = "MM.dd.yyyy"});

This solution doesn't work for me because it applies date format to all the properties. Is there any way to serialize each DateTime property with different format? Maybe there is some attribute?


Solution 1:

A straightforward way to handle this situation is to subclass the IsoDateTimeConverter to create a custom date converter for each different date format that you need. For example:

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

class LongDateConverter : IsoDateTimeConverter
{
    public LongDateConverter()
    {
        DateTimeFormat = "MMMM dd, yyyy";
    }
}

Then you can use the [JsonConverter] attribute to decorate the individual DateTime properties in any classes which need custom formatting:

class Foo
{
    [JsonConverter(typeof(MonthDayYearDateConverter))]
    public DateTime Date1 { get; set; }

    [JsonConverter(typeof(LongDateConverter))]
    public DateTime Date2 { get; set; }

    // Use default formatting
    public DateTime Date3 { get; set; }
}

Demo:

Foo foo = new Foo
{
    Date1 = DateTime.Now,
    Date2 = DateTime.Now,
    Date3 = DateTime.Now
};

string json = JsonConvert.SerializeObject(foo, Formatting.Indented);
Console.WriteLine(json);

Output:

{
  "Date1": "03.03.2014",
  "Date2": "March 03, 2014",
  "Date3": "2014-03-03T10:25:49.8885852-06:00"
}

Solution 2:

NewtonSoft.Json has a structure that's a bit difficult to understand, you can use something like the following custom converter to do what you want:

[TestMethod]
public void Conversion()
{
    var obj = new DualDate()
    {
        DateOne = new DateTime(2013, 07, 25),
        DateTwo = new DateTime(2013, 07, 25)
    };
    Assert.AreEqual("{\"DateOne\":\"07.25.2013\",\"DateTwo\":\"2013-07-25T00:00:00\"}", 
        JsonConvert.SerializeObject(obj, Formatting.None, new DualDateJsonConverter()));
}

class DualDate
{
    public DateTime DateOne { get; set; }
    public DateTime DateTwo { get; set; }
}

class DualDateJsonConverter : JsonConverter
{

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {

        JObject result = new JObject();

        DualDate dd = (DualDate)value;

        result.Add("DateOne", JToken.FromObject(dd.DateOne.ToString("MM.dd.yyyy")));
        result.Add("DateTwo", JToken.FromObject(dd.DateTwo));
        result.WriteTo(writer);
    }

    // Other JsonConverterMethods
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DualDate);
    }

    public override bool CanWrite
    {
        get
        {
            return true;
        }
    }
    public override bool CanRead
    {
        get
        {
            return false;
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Solution 3:

You can create a custom date class that inherits the IsoDateTimeConverter and pass a format on the constructor. On the attributes, you can specify which format corresponds to each property. See code below:

public class LoginResponse
{
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }
    [JsonProperty("token_type")]
    public string TokenType { get; set; }
    [JsonProperty("expires_in")]
    public DateTime ExpiresIn { get; set; }
    [JsonProperty("userName")]
    public string Username { get; set; }
    [JsonConverter(typeof(CustomDateFormat), "EEE, dd MMM yyyy HH:mm:ss zzz")]
    [JsonProperty(".issued")]
    public DateTime Issued { get; set; }
    [JsonConverter(typeof(CustomDateFormat), "MMMM dd, yyyy")]
    [JsonProperty(".expires")]
    public DateTime Expires { get; set; }
}

public class CustomDateFormat : IsoDateTimeConverter
{
    public CustomDateFormat(string format)
    {
        DateTimeFormat = format;
    }
}

Solution 4:

I realise this is an old question, but I stumbled upon it during my search for same question.

Newtonsoft has now a DateFormatString property in JsonSerializerSettings class which you can use. I came to this question looking for answer and have just found the property, I have used it as below and it works as below:

    private const string _StrDateFormat = "yyyy-MM-dd HH:mm:ss";

    private static string GetJSON(object value)
    {

        return JsonConvert.SerializeObject(value, new JsonSerializerSettings
        {
            DateFormatString = _StrDateFormat
        });
    }

When value will have a DateTime object, it will convert it into string respecting _StrDateFormat string.

Perhaps this official link can be updated?

Regards.