I'm using NodaTime for managing datetimes in my app, but have run into a problem with the way serialization is done in DocumentParser that prevents it from being used as a custom serialization converter.
There appears to be a longstanding issue with Json.Net about how it chooses to deserialize ISO datetimes (JamesNK/Newtonsoft.Json#862).
The issue is easiest to see when trying to load an object from an arango database that has an ISO date string valued property, and is being serialized into a .NET string property. Instead of the expected untouched ISO format (i.e. "2017-11-16T00:00:00Z"), the string is re-formatted using the standard DateTime string format (i.e. "11/16/2017 00:00:00").
The issue is that DocumentParser.ParseSingleResult uses a JsonReader which is automatically parsing the strings to datetimes. Unfortunately, JsonReader doesn't use the global arango serialization settings that specify to not do any date parsing. This settings needs to be manually applied to the reader i.e.
reader.DateParseHandling = DateParseHandling.None;
jObject = JObject.Load(reader);
var serializer = new DocumentSerializer(db).CreateJsonSerializer();
return jObject.ToObject<T>(serializer);
This seems like a quick fix though, as there are possibly other serialization settings being missed, and it might be better to change the usage of JObject.Load to an implementation that will apply the global serializer settings consistently.
In my case, this affects Nodatime's custom converters that are expecting the JToken being passed to it to be a String instead of a Date type. But I expect there may be cases where uses do not expect a date string to be changed
Test case to reproduce
public class Person
{
public string BirthDate { get; set; }
public string LastLogin { get; set; }
}
public class JsonSample
{
public static string SingleResult
{
get
{
return @"
{
'BirthDate':'1983-10-20',
'LastLogin':'2017-11-16T00:00:00Z',
'_id':'Person/KEY',
'_rev':'REV',
'_key':'KEY'
}
"; ;
}
}
[Fact]
public void ParseSingle()
{
using (var reader = GenerateReader(JsonSample.SingleResult))
{
var documentParser = new DocumentParser(new ArangoDatabase());
JObject jObject = null;
var person = documentParser.ParseSingleResult<Person>(reader, out jObject, true);
Assert.Equal("1983-10-20", person.BirthDate); // PASS - Dates appear to be OK
var lastLoginJToken = jObject["LastLogin"];
Assert.Equal(JTokenType.String, lastLoginJToken.Type); // FAILS - Type is Date
Assert.Equal("2017-11-16T00:00:00Z", person.LastLogin); // FAILS - Value is "11/16/2017 00:00:00"
}
}
I'm using NodaTime for managing datetimes in my app, but have run into a problem with the way serialization is done in
DocumentParser
that prevents it from being used as a custom serialization converter.There appears to be a longstanding issue with Json.Net about how it chooses to deserialize ISO datetimes (JamesNK/Newtonsoft.Json#862).
The issue is easiest to see when trying to load an object from an arango database that has an ISO date string valued property, and is being serialized into a .NET string property. Instead of the expected untouched ISO format (i.e. "2017-11-16T00:00:00Z"), the string is re-formatted using the standard DateTime string format (i.e. "11/16/2017 00:00:00").
The issue is that
DocumentParser.ParseSingleResult
uses aJsonReader
which is automatically parsing the strings to datetimes. Unfortunately, JsonReader doesn't use the global arango serialization settings that specify to not do any date parsing. This settings needs to be manually applied to the reader i.e.This seems like a quick fix though, as there are possibly other serialization settings being missed, and it might be better to change the usage of JObject.Load to an implementation that will apply the global serializer settings consistently.
In my case, this affects Nodatime's custom converters that are expecting the JToken being passed to it to be a String instead of a Date type. But I expect there may be cases where uses do not expect a date string to be changed
Test case to reproduce