-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow custom JsonConverters for base-classes #30427
Comments
Thanks for the detailed write-up and motivating scenario :)
As an aside, @martincostello discovered this error as well and it has been fixed: dotnet/corefx#39789 cc @steveharter |
Workaround without adding redundant convertersFor anyone who currently needs a workaround for this without adding all these additional converters, I might have a solution: If you make the
.. you have the possibility to declare the
You still need more |
Because we serialize with json.net and deserialize with System.Text.Json (involuntarily through jsruntime), we need a write-converter for json.net and a read-converter for system.text.json. sadly a lot of features are not yet present in system.text.json and so we can't use one converter attribute for the base-class but need one for every enum. This should change in .Net 5; progress is tracked at https://github.com/dotnet/corefx/issues/39905.
The factory pattern is the recommended way to handle polymorphic support - https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to#steps-to-follow-the-factory-pattern. The solution provided here #30427 (comment) is also correct. Please re-open if you still face problems. |
Does that mean you'll never support custom converters for base classes? I'm using blazor and currently JsRuntime doesn't support customized serialization so I rely on attributes. As far as I know (I haven't tested it in a while) I can't use a converter factory in combination with the |
Given the scenario where you can't easily configure a |
If I'm understanding the request correctly, it would be to expose an option like the following? [JsonConverter(typeof(ObjectEnumConverterFactory), isCovariantConverter: true)]
public abstract class ObjectEnum
{
}
public class SizeEnum : ObjectEnum // by default gets handled using a JsonConverter<SizeEnum> instance
// that is created by ObjectEnumConverterFactory
{
} I have a few concerns about adopting such a mechanism:
In light of the above, I don't think we should be adding this feature. It would serve a corner case with a known workaround and deserialization would be unsound for most use cases. cc @layomia @steveharter for thoughts. |
Triage: as stated above there are too many problems with adding such a feature and it really only serves to address a corner case that already has a known workaround. I'll be closing this issue, feel free to reopen if there is more to discuss about this. |
I'm currently trying to migrate from
Newtonsoft.Json
toSystem.Text.Json
and have to update my special enums (ObjectEnum
s). The main reason for that is simply becauseIJSRuntime
has been migrated toSystem.Text.Json
and my custom converters forNewtonsoft.Json
don't work anymore.Issue and solution
I have a base class called
ObjectEnum
. This class can be inherited to get an enum which has backing values of different types. It is used for strongly-typed JS-interops and thus needs a custom serializer.First of all let's look at
ObjectEnum
:Now one of the implementations:
Finally a use case:
Now if I just serialize
Config
without any custom converters I just get an empty object forSize
because the propertyValue
inObjectEnum
is notpublic
so nothing is serialized.With
Newtonsoft.Json
I had a really simple (write-only for simplicity here) Converter for this:I then put a
JsonConverterAttribute
to theObjectEnum
-class like so:[Newtonsoft.Json.JsonConverter(typeof(ObjectEnumConverter))]
All classes which derived from
ObjectEnum
automatically had this converter applied so I did not need to add this converter to any other class or create custom converters for each new enum. After adding the attribute to the class,Config
got serialized correctly (see below).Without attribute/custom serializer
With attribute/custom serializer
Now when porting everything to
System.Text.Json
I implemented aSystem.Text.Json.JsonConverter
forObjectEnum
just like I did withNewtonsoft.Json
(which was even easier). Before I show any code, yes, I checked all the Namespaces and ensured that I did not accidentally useNewtonsoft.Json
classes if I didn't intend to.Then I defined an attribute on my
ObjectEnum
just like I did before with the following code:[System.Text.Json.Serialization.JsonConverter(typeof(ObjectEnumConverter))]
Testing that resulted in an empty object just like without custom serializer (see above json). I also put a breakpoint in the
ObjectEnumConverter.Write
method and I can confirm that it never actually got to this converter.Next thing I tried was applying the attribute to the implementation. This means I put the same attribute-code on my
SizeEnum
-class.This resulted in a weird
FormatException
which you can see below.System.FormatException
Stacktrace:
Message:
Source:
System.Private.CoreLib
After that I created a new
JsonConverter
for mySizeEnum
. I only had to change the typeparam (and the name) from myObjectEnumConverter
.I used this converter in the
JsonConverterAttribute
onSizeEnum
like so:[System.Text.Json.Serialization.JsonConverter(typeof(SizeEnumConverter))]
This works! But I really don't think we want to persue this. It would be much more practical and nice if you were able to just put one converter for all
ObjectEnum
s on theObjectEnum
-class and this one would be used if there is not a more concrete one (basically the same behaviour likeNewtonsoft.Json
).Let me know what you think of this idea, I think it would be a great addition :)
Ps. It also doesn't work if you just use
JsonSerializer.Serialize
withJsonSerializerOptions
where you add a new instance ofObjectEnumConverter
to theConverters
property. This approach wouldn't work for me anyway since my concern isIJSRuntime
which currently doesn't support using your ownJsonSerializerOptions
.The text was updated successfully, but these errors were encountered: