Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deserialize a dictionary with NodaTime.Instant using Json.net without getting exception?

To serialize a dictionary with NodaTime.Instance to json using json.net works fine, but upon deserialization it throws Newtonsoft.Json.JsonSerializationException. The test below shows the problem:

[Test] 
public void DeserializeDictionaryThowsException() {
    JsonConverter[] converters = { NodaConverters.IntervalConverter, NodaConverters.InstantConverter };

    var dictionary = new Dictionary<Instant, int>() {
         {Instant.FromUtc(2012, 1, 2, 3, 4, 5), 0}
    };            
    var json = JsonConvert.SerializeObject(dictionary, Formatting.None, converters);
    Assert.AreEqual("{\"2012-01-02T03:04:05Z\":0}", json); //ok
    var result = JsonConvert.DeserializeObject<Dictionary<Instant, int>>(json, converters); // throws
}

DeserializeObject throws:

Newtonsoft.Json.JsonSerializationException : Could not convert string '2012-01-02T03:04:05Z' to dictionary key type 'NodaTime.Instant'. Create a TypeConverter to convert from the string to the key type object. Line 1, position 24. ----> Newtonsoft.Json.JsonSerializationException : Error converting value "2012-01-02T03:04:05Z" to type 'NodaTime.Instant'. Line 1, position 24. ----> System.Exception : Could not cast or convert from System.String to NodaTime.Instant.

As a side note, deserializing a Dictionary of DateTime works fine. I guess because String has a converter for DateTime.

[Test]
public void DeserializeDiciotnaryOfDateTime() // OK
{
    var expected = new DateTime(2012, 1, 2, 3, 4, 5, DateTimeKind.Utc);
    var dictionary = new Dictionary<DateTime, int>() { { expected, 0 } };
    var json = JsonConvert.SerializeObject(dictionary);       
    var result = JsonConvert.DeserializeObject<Dictionary<DateTime, int>>(json); 
    Assert.AreEqual(expected, dictionary.Keys.First()); // OK
}
like image 773
Rune Avatar asked Dec 18 '12 20:12

Rune


1 Answers

You need to add more JSON.NET converters to serialize NodaTime.Instance time as shown below.

public void DeserializeDictionaryThowsException()
{
    var dtzProvider = DateTimeZoneCache.GetSystemDefault();
    JsonConverter[] converters = { NodaConverters.IntervalConverter, 
                                   NodaConverters.InstantConverter,
                                   NodaConverters.LocalDateConverter,
                                   NodaConverters.LocalDateTimeConverter,
                                   NodaConverters.LocalTimeConverter,
                                   NodaConverters.OffsetConverter,
                                   NodaConverters.DurationConverter,
                                   NodaConverters.RoundtripPeriodConverter,
                                   NodaConverters.OffsetDateTimeConverter,
                                   NodaConverters.CreateDateTimeZoneConverter(dtzProvider),
                                   NodaConverters.CreateZonedDateTimeConverter(dtzProvider)
                                 };

    var dictionary = new Dictionary<Instant, int>() { { Instant.FromUtc(2012, 1, 2, 3, 4, 5), 0 } };
    var json = JsonConvert.SerializeObject(dictionary, Formatting.None, converters);
    Assert.AreEqual("{\"2012-01-02T03:04:05Z\":0}", json);
    var result = JsonConvert.DeserializeObject<Dictionary<Instant, int>>(json, converters);
}
like image 162
Alok Avatar answered Oct 24 '22 17:10

Alok