Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Json.Net cannot deserialize DateTime.MinValue

I've tried deserializing a Json string containing DateTime.MinValue in every conceivable way, but when the set method gets called on my object. The date always gets changed from -01-01-01- to -01-01-02-.

The Json being parsed clearly contains

"inception_date": "0001-01-01T00:00:00+00:00"

I then call JsonConvert on it:

return JsonConvert.DeserializeObject<T>(json, deserializerSettings);

Where T is a basic struct that contains a property: DateTime inception_date { get; set; } property. The deserializer settings are as follows:

deserializerSettings = new JsonSerializerSettings()
{
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
    DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc
};

Yet somewhere in the bowels of Newtonsoft.Json.dll, the above time gets converted to the following jObject.

"inception_date": "0001-01-02T00:00:00Z"

I have no way of stepping into their code, but by the damage is done before my code sees another call. ReadJson in the JsonConverter calls serializer.Populate(jObject.CreateReader(), target); where target is an instance of my class T, and jObject has somehow been rendered with the above incorrect date.

Can anyone figure out why this is happening or how I can prevent it? The jObject seems to be getting created in a way that is ignoring my serializer settings, which explicitly say not to screw with the date string (DateParseHandling.None).


I've taken screen shots to illustrate exactly where Newtonsoft's JsonConvert method seems to have lost a vital configuration value.

As you can see, this is the point in the code where I call JsonConvert:

enter image description here

The dateParseHandling value is set to None, and that's how it should be for this to work.

At this next step, I've jumped a few internal Newtonsoft calls and landed in a generic implementation of the JsonConverter which I borrowed from an accepted reference implementation to be able to see what was going on. The JsonReader passed in suddenly has lost that dateParseHandling value:

enter image description here

Because of this value being switched back to DateTime - the internal workings of the jObject try to represent this as an internal localized DateTime, which underflows because my timezone is negative, and we're already representing the minimum DateTime value, resulting in the conversion back to UTC adding a full day.

like image 285
Alain Avatar asked Oct 21 '22 15:10

Alain


1 Answers

Try:

deserializerSettings = new JsonSerializerSettings()
{
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    DateParseHandling = Newtonsoft.Json.DateParseHandling.DateTimeOffset
}

This resulted in me getting 1/1/0001 12:00:00 AM instead of 1/2/0001 12:00:00 AM

Here is my test code (written in LINQPad)

void Main()
{
    var deserializerSettings = new JsonSerializerSettings()
    {
        DateFormatHandling = DateFormatHandling.IsoDateFormat,
        DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
        DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc
    };
    var json = "{\"inception_date\": \"0001-01-01T00:00:00+00:00\"}";
    var parsedObj = JsonConvert.DeserializeObject<TestClass>(json, deserializerSettings);
    Console.WriteLine(parsedObj);

    deserializerSettings = new JsonSerializerSettings()
    {
        DateFormatHandling = DateFormatHandling.IsoDateFormat,
        DateParseHandling = Newtonsoft.Json.DateParseHandling.DateTimeOffset
    };
    parsedObj = JsonConvert.DeserializeObject<TestClass>(json, deserializerSettings);
    Console.WriteLine(parsedObj);
}

public class TestClass
{
    public DateTime inception_date {get;set;}
}

Outputs:

OutputFromProgram

like image 141
Pete Garafano Avatar answered Nov 02 '22 09:11

Pete Garafano