08Dc91wk
08Dc91wk

Reputation: 4318

Using Newtonsoft JToken.ToObject<T> to deserializeNodaTime Instant

I am using NodaTime throughout my project as a replacement for the standard BCL DateTime classes, with amazing results.

I would like to banish DateTime from my project completely. I am only using it in one place - where I deserialize a large JSON file that contains dates. These dates are always UTC and always specified in ISO 8601 format.

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;

namespace Foo.Parsing
{
public class Parser
{
    JSchema schema;
    JObject jsonObject;

    public Parser(string jsonContent, string schemaString)
    {
        schema = JSchema.Parse(schemaString);
        jsonObject = JObject.Parse(jsonContent);
    }

    public MyObject Parse()
    {
        return jsonObject.ToObject<MyObject>();
    }
}

public class MyObject
{
     [JsonProperty(Required = Required.Always)]
     public DateTime date { get; set; }

     // A lot of other properties here.
}
}

This all works extremely well, but at the moment I have to use Instant.FromDateTimeUtc(myObject.date); to convert the DateTimes to Instant. Inside MyObject I have DateTimes and if I try to change this to Instant, I get the following error:

Newtonsoft.Json.JsonSerializationException' in Newtonsoft.Json.dll Additional information: Error converting value 2016/07/07 12:00:00 AM to type 'NodaTime.Instant'. Path 'date', line 4, position 37

Is there any way for me to deserialize my JSON file to my strongly typed MyObject, with my dates deserializing directly to Instant instead of having to convert a DateTime?

Upvotes: 2

Views: 1912

Answers (1)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241555

Per the Noda Time User Guide:

If you're still getting "Unexpected token..." messages, then likely you have changed the DateParseHandling setting. The ConfigureForNodaTime call will set this to DateParseHandling.None, and it should be left that way.

Note that this works well with the JsonConvert.SerializeObject and JsonConvert.DeserializeObject classes, as they accept a JsonSettings parameter, which can also be set via JsonConvert.DefaultSettings. Here is a live demo using this approach.

However, if you're using the JObject APIs, there is one slight problem. JObject.Parse has no ability to take a settings parameter, and by default you won't have the DateParseHandling.None that is required at this stage. The solution to this involves using a JsonTextReader, and is described well in this StackOverflow answer.

Upvotes: 3

Related Questions