Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialize NodaTime JSON

I am making a prototype project of NodaTime compared to BCL's DateTime, but executing this result gives me recursionLimit exceeded error.

Recursion limit exceeded

This is the function I am using to JSONify my viewmodel. The error happens after this function returns.

    [HttpPost]
    public JsonResult GetDates(int numOfDatesToRetrieve)
    {
        List<DateTimeModel> dateTimeModelList = BuildDateTimeModelList(numOfDatesToRetrieve);

        JsonResult result = Json(dateTimeModelList, JsonRequestBehavior.AllowGet);
        return result;
    }

My view model is built properly when I inspected it. Here is the code for my view model.

public class DateTimeModel
{
    public int ID;

    public LocalDateTime NodaLocalDateTimeUTC;
    public LocalDateTime NodaLocalDateTime
    {
        get
        {
            DateTimeZone dateTimeZone = DateTimeZoneProviders.Bcl.GetZoneOrNull(BCLTimezoneID);

            //ZonedDateTime zonedDateTime = NodaLocalDateTimeUTC.InUtc().WithZone(dateTimeZone);

            OffsetDateTime offsetDateTime = new OffsetDateTime(NodaLocalDateTimeUTC, Offset.Zero);
            ZonedDateTime zonedDateTime = new ZonedDateTime(offsetDateTime.ToInstant(), dateTimeZone);
            return zonedDateTime.LocalDateTime;
        }
    }

    public OffsetDateTime NodaOffsetDateTime;

    public DateTime BclDateTimeUTC;
    public DateTime BclLocalDateTime
    {
        get
        {
            DateTime utcDateTime = DateTime.SpecifyKind(BclDateTimeUTC, DateTimeKind.Utc);
            TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(BCLTimezoneID);
            DateTime result = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone);
            return result;
        }
    }

    public DateTimeOffset BclDateTimeOffset;
    //public int Offset;
    public string OriginalDateString;
    public string BCLTimezoneID;
}

I am sure that the NodaTime objects are not serializing correctly because when I comment the code from the viewModel the JsonResult is able to execute.

I read this off this page NodaTime API Reference

Code in this namespace is not currently included in Noda Time NuGet packages; it is still deemed "experimental". To use these serializers, please download and build the Noda Time source code from the project home page.

So I downloaded and built the source code and replaced the dll's my project references but I don't know how to implement the JsonSerialization classes.

Can someone explain to me how to use NodaTime.Serialization.JsonNet classes to make my NodaTime objects serializable?

like image 914
mac10688 Avatar asked Feb 10 '13 21:02

mac10688


2 Answers

We don't currently have any support for JavaScriptSerializer: I suspect you'll have to use Json.NET for all your JSON serialization. The user guide page on serialization gives a little bit more information, but it does mostly assume you already know about Json.NET.

The good news is that Json.NET is pretty easy to use - you may well find it's as simple as:

var settings = new JsonSerializerSettings();
settings.ConfigureForNodaTime();
string json = JsonConvert.SerializeObject(model, settings);

(Or use JsonSerializer.)

As an aside, the way you're using the Noda Time types is a little odd to say the least - it may well be worth asking another question with details of what you're trying to achieve, and we can work out a more idiomatic way of doing it :)

like image 134
Jon Skeet Avatar answered Oct 25 '22 08:10

Jon Skeet


Serialization is supported for JSON.NET in Noda Time 2.0+.

You'll need to install the package with NuGet:

> Install-Package NodaTime.Serialization.JsonNet

And then configure your serializer settings to use it. This won't work with the default serializer/deserializer - you need to configure one explicitly.

We chose to use one statically. Your usage may be different. Here is an example:

using Newtonsoft.Json;
using NodaTime;
using NodaTime.Serialization.JsonNet; // << Needed for the extension method to appear!
using System;

namespace MyProject
{
    public class MyClass
    {
        private static readonly JsonSerializerSettings _JsonSettings;

        static MyClass()
        {
            _JsonSettings = new JsonSerializerSettings
            {
                // To be honest, I am not sure these are needed for NodaTime,
                // but they are useful for `DateTime` objects in other cases.
                // Be careful copy/pasting these.
                DateFormatHandling = DateFormatHandling.IsoDateFormat,
                DateTimeZoneHandling = DateTimeZoneHandling.Utc,
            };

            // Enable NodaTime serialization
            // See: https://nodatime.org/2.2.x/userguide/serialization
            _JsonSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
        }

        // The rest of your code...
    }
}
like image 27
jocull Avatar answered Oct 25 '22 06:10

jocull