Closed jongeorge1 closed 3 years ago
I'm happy with this solution - but I think it needs to go into the "standard usage" in the README, to avoid surprises.
What about other "well known" types like Guids?
Updated the readme.md and added specs to demonstrate the expected behaviour of other "special case" types.
As a result of the recent changes to this library to provide support for conversion of
IPropertyBag
toIReadOnlyDictionary<string, object>
, we have encountered some issues due to unexpected behaviour in Json.Net.Our initial implementation checks each value in the bag to map its token type to a list of recognised values. If any unexpected token types are found during enumeration, an exception is thrown.
We have now discovered that depending on the
JsonSerializerSettings
in use, there may be token types we weren't expecting - the case we found was when string values are detected to be dates based on theJsonSerializerSettings.DateParseHandling
setting. In this case, Json.Net will report the token type asJTokenType.Date
, which caused our enumeration code to throw.We don't want to add an equivalent of DateTime to our list of recognised values, because this "helpful" feature of determining that a string is a date is specific to Newtonsoft.Json - it is not related to any underlying part of the JSON spec, and it isn't present in System.Text.Json. As a result, we have taken the decision to return any "unrecognised" token type as a string rather than throwing an exception, because ultimately any unrecognised token type must be represented in the underlying JSON as a string.
This causes some issues when
JsonSerializerSettings.DateParseHandling
is set toDateTimeOffset
(our current default) orDateTime
; attempting to retrieve a value deserialized using these settings as a string results in a date/time string with non-standard formatting (i.e. the source string2021-02-15T12:00:00.0000Z
is returned as02/15/2021 12:00:00 + 00:00
, rather than in its original form.In order to try and keep the behaviour of the dictionary conversion as predictable as possible, we've modified our
JsonSerializerSettingsProvider
to setJsonSerializerSettings.DateParseHandling
toNone
. This means Json.Net won't attempt to do any clever conversion by default.This only affects working with JSON data using the
Newtonsoft.Json.Linq
namespace - standard serialization/deserialization to/fromDateTime
andDateTimeOffset
is not affected. However, to support backwards compatibility when this is required, we've added the ability to modify the serializer settings created by theJsonSerializerSettingsProvider
at the point it's registered.We've also had to modify the
DateTimeOffsetConverter
to take account of this, previously it relied onJsonSerializerSettings.DateParseHandling
being set toDateTimeOffset
; now it can cope withDateTimeOffset
orNone
. It can't cope withDateTime
because we believe using theDateTimeOffsetConverter
but setting up yourJsonSerializerSettings
in this way are mutually incompatible.