You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As demonstrated in dotnetfiddle, the values that result for DateTime/DateTimeOffset fields when deserialized using JsonSubtypes are different than using stock Newtonsoft converter.
JsonSubtypes provides an excellent way for handling inheritance, however the method by which it does this should not result in the target object values being different than when using stock deserialization. For example, when OrderBase uses JsonSubtype and Order does not and there is a DateTime and DateTimeOffset property on each object, the values should be identical across subtype and stock:
The reason for the difference is that JsonSubtypes uses a two-step process in order to determine the type to deserialize to: 1) Deserialize to JObject; and then 2) Deserialize to target type. Step 1 should not perform any deserialization itself and the original json should effectively pass thru untouched since its only purpose is to obtain the target type. Step 2 should be responsible for the deserialization. Currently, some deserialization occurs in Step 1 around dates which leads to the behavior difference from stock deserialization.
When deserializing to JObject, since there isn't a known target type for a property, the JToken for a property that "looks like" (see here for history) a DateTime/DateTimeOffset will become a JToken with type Date and the value will be either DateTime or DateTimeOffset depending on JsonSerializerSettings.DateParseHandling value (see default case of JsonTextReader). At this point, the value is already typed so when it passes through step 2 of deserialization, it's simply converted to the target property type from the known class type rather than converted from its raw value to the target property type like would be the case in stock deserialization.
In stock deserialization to a type, the type information is used as strings that "look like" DateTime/DateTimeOffset are handled according to their target type (see here and here). This avoids having to rely on DateParseHandling value.
In v1.8, a fix (#113) was made to address this, however it was removed in v2.0 (#120) with the recommended solution being to specify DateTimeOffset for DateParseHandling. Unfortunately, even specifying DateTimeOffset does not address the underlying issue because the problem just shifts to having DateTime values different than stock deserilization to DateTime values.
Date & DateTimeOffset values are identical when deserializing SubTypeOrder (via JsonSubtypes) and Order (via stock Newtonsoft)
Actual behavior
When using JsonSerializerSettings defaults
SubTypeOrder.DateTimeOffset: 09/14/2011 04:00:00 +00:00
Order.DateTimeOffset: 09/14/2011 00:00:00 -04:00
When using recommended solution from #120 (passing DateParseHandling.Offset)
SubTypeOrder.DateTime: 09/14/2011 00:00:00
Order.DateTime: 09/14/2011 04:00:00
As demonstrated in dotnetfiddle, the values that result for DateTime/DateTimeOffset fields when deserialized using JsonSubtypes are different than using stock Newtonsoft converter.
JsonSubtypes provides an excellent way for handling inheritance, however the method by which it does this should not result in the target object values being different than when using stock deserialization. For example, when
OrderBase
uses JsonSubtype andOrder
does not and there is aDateTime
andDateTimeOffset
property on each object, the values should be identical acrosssubtype
andstock
:The reason for the difference is that JsonSubtypes uses a two-step process in order to determine the type to deserialize to: 1) Deserialize to JObject; and then 2) Deserialize to target type. Step 1 should not perform any deserialization itself and the original json should effectively pass thru untouched since its only purpose is to obtain the target type. Step 2 should be responsible for the deserialization. Currently, some deserialization occurs in Step 1 around dates which leads to the behavior difference from stock deserialization.
When deserializing to JObject, since there isn't a known target type for a property, the JToken for a property that "looks like" (see here for history) a DateTime/DateTimeOffset will become a JToken with type Date and the value will be either DateTime or DateTimeOffset depending on JsonSerializerSettings.DateParseHandling value (see default case of JsonTextReader). At this point, the value is already typed so when it passes through step 2 of deserialization, it's simply converted to the target property type from the known class type rather than converted from its raw value to the target property type like would be the case in stock deserialization.
In stock deserialization to a type, the type information is used as strings that "look like" DateTime/DateTimeOffset are handled according to their target type (see here and here). This avoids having to rely on DateParseHandling value.
In v1.8, a fix (#113) was made to address this, however it was removed in v2.0 (#120) with the recommended solution being to specify DateTimeOffset for DateParseHandling. Unfortunately, even specifying DateTimeOffset does not address the underlying issue because the problem just shifts to having DateTime values different than stock deserilization to DateTime values.
Source/destination types
Source/destination JSON
Expected behavior
Date & DateTimeOffset values are identical when deserializing SubTypeOrder (via JsonSubtypes) and Order (via stock Newtonsoft)
Actual behavior
When using JsonSerializerSettings defaults
SubTypeOrder.DateTimeOffset: 09/14/2011 04:00:00 +00:00
Order.DateTimeOffset: 09/14/2011 00:00:00 -04:00
When using recommended solution from #120 (passing DateParseHandling.Offset)
SubTypeOrder.DateTime: 09/14/2011 00:00:00
Order.DateTime: 09/14/2011 04:00:00
Steps to reproduce
See dotnetfiddle
The text was updated successfully, but these errors were encountered: