Question

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?

Was it helpful?

Solution

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);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top