Polymorphic deserialization with System.Text.Json
requires discriminator property to have the shortest JSON object key length
#2590
-
The following sample only works due to overriding the default discriminator property named [JsonPolymorphic(TypeDiscriminatorPropertyName = "$t")]
[JsonDerivedType(typeof(WeatherForecastBase), typeDiscriminator: "base")]
[JsonDerivedType(typeof(WeatherForecastWithCity), typeDiscriminator: "withCity")]
public class WeatherForecastBase
{
public DateTimeOffset Date { get; set; } // key length = 4
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
public class WeatherForecastWithCity : WeatherForecastBase
{
public string? City { get; set; } // key length = 4
} The System.Text.Json (STJ) docs state:
It's a pretty annoying .NET runtime issue that has been raised upstream. Not sure why STJ is opinionated about that, maybe for backwards compatibility with legacy systems? 🤔 This conflicts with
Should we mention this quirk in the docs under Serialization with System.Text.Json? Another idea is to let Marten align STJ and Similar to the public class SystemTextJsonContractResolver : DefaultJsonTypeInfoResolver
{
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
{
var jsonTypeInfo = base.GetTypeInfo(type, options);
var isPolymorphic = type
.GetCustomAttributes(typeof(JsonDerivedTypeAttribute))
.Any();
if (isPolymorphic)
{
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
{
TypeDiscriminatorPropertyName = "$t"
// that works too and is even shorter
// TypeDiscriminatorPropertyName = "!"
};
}
return jsonTypeInfo;
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments
-
|
Beta Was this translation helpful? Give feedback.
-
This is like a self-referential issue, I opened the original issue in the runtime repo due to discovering the problem whilst testing marten with STJ polymorphism and now it's come full circle and ended up back here. 😆 Use of a shorter type discriminator is an interesting solution, but I personally see it as a "hack" rather than "fix" as such a short discriminator is not the norm within the ecosystem and would make migrating from newtonsoft polymorphism & other STJ polymorphic packages more difficult. Thus I wouldn't expect marten to patch this out of the box with a contract resolver. Adding something to docs mentioning this issue and some potential workarounds seems reasonable. I'm still fine with using the PolyJson package until STJ resolves the particular issue. |
Beta Was this translation helpful? Give feedback.
-
Seems reasonable. Another option could be allowing users to override the default Marten contract resolver via Marten store options. Without having looked at the code, I could imagine that this could potentially lead to more issues down the road. |
Beta Was this translation helpful? Give feedback.
-
My personal take on this is that the STJ is terrible in that regard; some of the reasons you already mentioned. I also don’t see much benefit of having polymorphism in DTOs. You can override the STJ settings, AFAIK we’re not blocking anything here. If we do, then happy to enable that. I’m sorry, but I don’t see happening changing the way we serialise things just to enable this specific feature as it’s too high risk for too small a reward. I’ll turn this into the discussion for now. |
Beta Was this translation helpful? Give feedback.
My personal take on this is that the STJ is terrible in that regard; some of the reasons you already mentioned. I also don’t see much benefit of having polymorphism in DTOs.
You can override the STJ settings, AFAIK we’re not blocking anything here. If we do, then happy to enable that.
I’m sorry, but I don’t see happening changing the way we serialise things just to enable this specific feature as it’s too high risk for too small a reward.
I’ll turn this into the discussion for now.