Home > Back-end >  JsonSerializer errors out deserializing dictionary of objects
JsonSerializer errors out deserializing dictionary of objects

Time:09-28

I'm having trouble deserializing a Json serialized dictionary of objects.

Here is some code to replicate the issue.

using System.Text.Json;

// my dictionary of objects
var dict = new Dictionary<string, object>();
dict.Add("test-date", DateTime.MaxValue);

// serialize the dictionary
var serialized = JsonSerializer.Serialize(dict);        // --> returns serialized = {"test-date":"9999-12-31T23:59:59.9999999"}

// deserialize the dictionary
dict = JsonSerializer.Deserialize<Dictionary<string, object>>(serialized);

DateTime testDate = (DateTime)dict["test-date"];       // --> throws System.InvalidCastException - Specified cast is not valid.

Does anyone know what could be the problem and any possible workarounds for it?

CodePudding user response:

If you look at the JSON after the serialization, the DateTime is contained as a string (there is no data type for DateTimes in JSON). When deserializing to a Dictionary<string, object>, the JsonSerializer does not have any information on how the string that it reads should be interpreted (though a human most likely can see that it is a datetime value). Hence, it uses the generic type JsonElement to store the data. You cannot cast a JsonElement to a DateTime because there are different ways on how to interpret the data.

There are several ways to overcome this:

  • If you know that all the values in the dictionary are DateTime values, change the type of the dictionary to Dictionary<string, DateTime>. Then the deserializer knows how to interpret the data.
  • If this is not possible, you can try to implement a custom serializer that analyses the JSON and checks whether the value can be converted to a DateTime. However, if there are various types to consider, this might proove to be a tedious task.
  • If you only need to check this at a single location, and if you know for sure that the value is a DateTime, you can use the following code to get a DateTime:

var jsonElement = (JsonElement)dict["test-date"];
var dt = jsonElement.GetDateTime();

Also, you could retrieve the value as a string and be more cautious when parsing:

var s = jsonElement.GetString();
if (DateTime.TryParse(s, out var dt2))
    // ...

See this fiddle to test.

CodePudding user response:

Just in one line

DateTime testDate = Convert.ToDateTime(dict["test-date"].ToString()); //9999-12-31 11:59:59 PM

or my usuall advise: Use Newtonsoft.Json and your life will be much easier.

using Newtonsoft.Json;

DateTime testDate = (DateTime) dict["test-date"];
  • Related