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 toDictionary<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 aDateTime
:
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"];