JSON.NET Serialize DateTime.MinValue as null

13,144

Solution 1

Create a custom converter which serializes DateTime.MinValue into null, and (if required) deserializes null into DateTime.MinValue:

public class MinDateTimeConverter : DateTimeConverterBase
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.Value == null)
            return DateTime.MinValue;

        return (DateTime)reader.Value;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        DateTime dateTimeValue = (DateTime)value;
        if (dateTimeValue == DateTime.MinValue)
        {
            writer.WriteNull();
            return;
        }

        writer.WriteValue(value);
    }
}

You can then use attributes to add the converter to your data class, as shown in this example:

public class Example
{
    [JsonConverter(typeof(MinDateTimeConverter))]
    public DateTime ValueOne { get; set; }

    [JsonConverter(typeof(MinDateTimeConverter))]
    public DateTime ValueTwo { get; set; }
}

public static void Main(string[] args)
{
    Example data = new Example();
    data.ValueOne = DateTime.MinValue;
    data.ValueTwo = DateTime.Now;

    JsonSerializer serializer = new JsonSerializer();

    using (StringWriter writer = new StringWriter())
    {
        serializer.Serialize(writer, data);
        Console.Write(writer.ToString());
    }

    Console.ReadKey();
}

Console output:

{"ValueOne":null,"ValueTwo":"2016-10-26T09:54:48.497463+01:00"}

Solution 2

Custom DateTime Json Converter

public class DateTimeConverter : JsonConverter
{   
    public override void WriteJson(JsonWriter jsonWriter, object inputObject,JsonSerializer jsonSerializer)
    {
        // Typecast the input object
        var dateTimeObject = inputObject as DateTime?;

        // Set the properties of the Json Writer
        jsonWriter.Formatting = Newtonsoft.Json.Formatting.Indented;

        if(dateTimeObject == DateTime.MinValue)
            jsonWriter.WriteValue((DateTime?)null);
        else
            jsonWriter.WriteValue(dateTimeObject);
    }


    public override object ReadJson(JsonReader reader,
        Type objectType,
        object existingValue,
        JsonSerializer serializer)
    {
        DateTime? readValue = reader.ReadAsDateTime();

        return (readValue == null) ? DateTime.MinValue : readValue;     

    }


    public override bool CanConvert(Type objectType)
    {
        return typeof(DateTime?).IsAssignableFrom(objectType);
    }
}

Usage:

public class DateTest
{
    [JsonConverterAttribute(typeof(DateTimeConverter))]
    public DateTime? MyDateTime { get; set;}

    [JsonConverterAttribute(typeof(DateTimeConverter))]
    public DateTime? MyDateTime1 { get; set; }
}

void Main()
{
    DateTest dateTest = new DateTest 
    { 
      MyDateTime = DateTime.MinValue, 
      MyDateTime1 = DateTime.MaxValue
    };

    Console.WriteLine(JsonConvert.SerializeObject(dateTest));
}

Result:

{
  "MyDateTime": null,
  "MyDateTime1": "9999-12-31T23:59:59.9999999"
}

Solution 3

Not 100% clear on why the original poster wanted this and it's 5 years down the line but I too wanted to achieve this.

However, in my case the issue was that when I serialised my object it was inserting the DateTime fields because they hadn't been specified on the incoming object but were being returned as MinValue not null.

Thus when I deserialised at the other end these fields were showing as 'dirty' and being parsed.

In this case you can just amend your JsonSerializerSettings block to include 'ignore' in the default value handling:

string serialisedMessage = JsonConvert.SerializeObject(message, new JsonSerializerSettings
        {
            NullValueHandling = NullValueHandling.Ignore,
            DefaultValueHandling = DefaultValueHandling.Ignore
        });

So I'm leaving this in case of future users who are in my position.

Share:
13,144

Related videos on Youtube

Mick
Author by

Mick

Microsoft Software developer with 20+ years experience and the plus just keeps on getting bigger.

Updated on September 15, 2022

Comments

  • Mick
    Mick over 1 year

    I'd like DateTime fields that are set to DateTime.MinValue returned by my Web API to be serialized to NULL instead of "0001-01-01T00:00:00".

    I understand there's a way to get JSON.NET to omit fields that are set to default values, but I would prefer JSON.NET to specifically serialize DateTime MinValue / "0001-01-01T00:00:00" as null.

    Is there a way to do this?

  • dbc
    dbc over 7 years
    DateTimeConverterBase also accepts DateTimeOffset so you need to modify CanConvert to only return true for DateTime and DateTime?
  • Alsty
    Alsty over 7 years
    @dbc This converter will only work when directly applied to DateTime properties using a JsonConverter attribute. CanConvert is not called in this scenario. ReadJson would need to be modified if DateTime? types need to be supported.