Specifying a custom DateTime format when serializing with Json.Net

C#Datetimeasp.net Web-Apijson.net

C# Problem Overview


I am developing an API to expose some data using ASP.NET Web API.

In one of the API, the client wants us to expose the date in yyyy-MM-dd format. I don't want to change the global settings (e.g. GlobalConfiguration.Configuration.Formatters.JsonFormatter) for that since it is very specific to this client. And I do developing that in a solution for multiple clients.

One of the solution that I could think of is to create a custom JsonConverter and then put that to the property I need to do the custom formatting

e.g.

class ReturnObjectA 
{
    [JsonConverter(typeof(CustomDateTimeConverter))]
    public DateTime ReturnDate { get;set;}
}

Just wondering if there is some other easy way of doing that.

C# Solutions


Solution 1 - C#

You are on the right track. Since you said you can't modify the global settings, then the next best thing is to apply the JsonConverter attribute on an as-needed basis, as you suggested. It turns out Json.Net already has a built-in IsoDateTimeConverter that lets you specify the date format. Unfortunately, you can't set the format via the JsonConverter attribute, since the attribute's sole argument is a type. However, there is a simple solution: subclass the IsoDateTimeConverter, then specify the date format in the constructor of the subclass. Apply the JsonConverter attribute where needed, specifying your custom converter, and you're ready to go. Here is the entirety of the code needed:

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

If you don't mind having the time in there also, you don't even need to subclass the IsoDateTimeConverter. Its default date format is yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK (as seen in the source code).

Solution 2 - C#

You could use this approach:

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

And use it this way:

class ReturnObjectA 
{
    [JsonConverter(typeof(DateFormatConverter), "yyyy-MM-dd")]
    public DateTime ReturnDate { get;set;}
}

The DateTimeFormat string uses the .NET format string syntax described here: https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings

Solution 3 - C#

It can also be done with an IsoDateTimeConverter instance, without changing global formatting settings:

string json = JsonConvert.SerializeObject(yourObject,
    new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });

This uses the JsonConvert.SerializeObject overload that takes a params JsonConverter[] argument.

Solution 4 - C#

Also available using one of the serializer settings overloads:

var json = JsonConvert.SerializeObject(someObject, new JsonSerializerSettings() { DateFormatString = "yyyy-MM-ddThh:mm:ssZ" });

Or

var json = JsonConvert.SerializeObject(someObject, Formatting.Indented, new JsonSerializerSettings() { DateFormatString = "yyyy-MM-ddThh:mm:ssZ" });

Overloads taking a Type are also available.

Solution 5 - C#

There is another solution I've been using. Just create a string property and use it for json. This property wil return date properly formatted.

class JSonModel {
	...

	[JsonIgnore]
	public DateTime MyDate { get; set; }

	[JsonProperty("date")]
	public string CustomDate {
		get { return MyDate.ToString("ddMMyyyy"); }
		// set { MyDate = DateTime.Parse(value); }
		set { MyDate = DateTime.ParseExact(value, "ddMMyyyy", null); }
	}

	...
}

This way you don't have to create extra classes. Also, it allows you to create diferent data formats. e.g, you can easily create another Property for Hour using the same DateTime.

Solution 6 - C#

With below converter

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

        public CustomDateTimeConverter(string format)
        {
            DateTimeFormat = format;
        }
    }

Can use it with a default custom format

class ReturnObjectA 
{
    [JsonConverter(typeof(CustomDateTimeConverter))]
    public DateTime ReturnDate { get;set;}
}

Or any specified format for a property

class ReturnObjectB 
{
    [JsonConverter(typeof(CustomDateTimeConverter), "dd MMM yy")]
    public DateTime ReturnDate { get;set;}
}

Solution 7 - C#

public static JsonSerializerSettings JsonSerializer { get; set; } = new JsonSerializerSettings()
		{
			DateFormatString= "yyyy-MM-dd HH:mm:ss",
			NullValueHandling = NullValueHandling.Ignore,
			ContractResolver = new LowercaseContractResolver()
		};

Hello,

I'm using this property when I need set JsonSerializerSettings

Solution 8 - C#

Some times decorating the json convert attribute will not work ,it will through exception saying that "2010-10-01" is valid date. To avoid this types i removed json convert attribute on the property and mentioned in the deserilizedObject method like below.

var addresss = JsonConvert.DeserializeObject<AddressHistory>(address, new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd" });

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionStay FoolishView Question on Stackoverflow
Solution 1 - C#Brian RogersView Answer on Stackoverflow
Solution 2 - C#Keith HillView Answer on Stackoverflow
Solution 3 - C#Saeb AminiView Answer on Stackoverflow
Solution 4 - C#MattView Answer on Stackoverflow
Solution 5 - C#Antonio RodríguezView Answer on Stackoverflow
Solution 6 - C#RangaView Answer on Stackoverflow
Solution 7 - C#Ricardo BeckView Answer on Stackoverflow
Solution 8 - C#Muni ChittemView Answer on Stackoverflow