Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing Noda Time's LocalDateTime with JSON.NET

I'm trying to use Json.NET to serialize some Noda Time values and having trouble. Serialization is simple enough:

LocalDateTime dt = ... // Assigned elsewhere
LocalDateTimePattern isoDateTimePattern = LocalDateTimePattern.GeneralIsoPattern;
JObject root = new JObject();
root.Add("time", isoDateTimePattern.Format(dt));

// Serialize other elements

using (var sw = new StreamWriter(stream)) {
    serializer.Serialize(sw, root);
}

But deserialization is problematic. Json.NET seems to recognize the ISO-formatted date and time from above and automatically convert it into a DateTime object, which is not what I want.

using (var sr = new StreamReader(stream)) {
        using (var jr = new JsonTextReader(sr)) {
            var root = serializer.Deserialize<JObject>(jr);

            // Deserialize other elements

            var time = root.GetValue("time"); // time.Type is JTokenType.Date
            string timeStr = time.Value<string>(); // Is "01/10/2014 10:37:32"

            // Kaboom. String is not in the right format (see above comment)
            var parsedTime = isoDateTimePattern.Parse(time.Value<string>());
        }
}

From the fact that timeStr comes out as a US-formatted date and time, I would guess that time.Value<string>() just calls ToString on some internal DateTime object that Json.NET has already parsed. I could do something like

var cdt = time.Value<DateTime>();
LocalDateTime ldt = new LocalDateTime(cdt.Year, cdt.Month, cdt.Day, cdt.Hour, cdt.Minute);

but that's convoluted and means Json.NET is performing unneeded conversions.

Is there any way to just get the raw string value of a JSON value?

like image 334
Matt Kline Avatar asked Jan 10 '14 16:01

Matt Kline


1 Answers

There is a NodaTime.Serialization.JsonNet package available on NuGet that seems to be aimed exactly at this situation. Here is how to set it up:

After downloading and installing the package in your solution, add the following using statement to your code:

using NodaTime.Serialization.JsonNet;

Set up your serializer like this:

JsonSerializer serializer = new JsonSerializer();
serializer.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);

Then, when you deserialize, you can get a LocalDateTime from the JObject using ToObject<LocalDateTime>(serializer) like this:

using (var sr = new StreamReader(stream))
{
    using (var jr = new JsonTextReader(sr))
    {
        var root = serializer.Deserialize<JObject>(jr);

        // Deserialize other elements

        var time = root.GetValue("time");
        var parsedTime = time.ToObject<LocalDateTime>(serializer);
    }
}
like image 70
Brian Rogers Avatar answered Nov 06 '22 20:11

Brian Rogers