Skip to content
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

Use native attributes for polymorphism in System.Text.Json #1739

Open
marinasundstrom opened this issue Oct 25, 2024 · 4 comments
Open

Use native attributes for polymorphism in System.Text.Json #1739

marinasundstrom opened this issue Oct 25, 2024 · 4 comments

Comments

@marinasundstrom
Copy link

marinasundstrom commented Oct 25, 2024

TL;DR;

When handling polymorphism in System.Text.Json, the generator should emit JsonPolymorphic and JsonDerivedType.

Background

I have been using System.Text.Json as a target library for my projects. And I have discovered an issue with the generated C# client with regard to inheritance.

https://github.com/RicoSuter/NJsonSchema/blob/9bf8f695b373410e8b51e1363270c08dda7b8127/src/NJsonSchema.CodeGeneration.CSharp/Templates/JsonInheritanceConverter.liquid

Some context: Both server and generated C# client use System.Text.Json.

Problem

In the client, the generated special inheritance converter and attributes don't work for me since the serialized JSON always contain a double set of the discriminator.

{"species":"Dog","foo":true,"species":"Dog"}

This is due to the converter adding that. And the serializer doesn't like it.

"The metadata property is either not supported by the type or is not the first property in the deserialized JSON object

Proposal

I have experimented with manually changing the attributes to the build in ones: JsonPolymorphic and JsonDerivedType

So instead of this:

    [JsonInheritanceConverter(typeof(Animal), "species")]
    [JsonInheritanceAttribute("Dog", typeof(AnimalDog))]
    [JsonInheritanceAttribute("Cat", typeof(AnimalCat))]

We should have an option to have this generated when using System.Text.Json:

    [JsonPolymorphic(TypeDiscriminatorPropertyName = "species")]
    [JsonDerivedType(typeof(AnimalDog), "Dog")]
    [JsonDerivedType(typeof(AnimalCat), "Cat")]

That would at least solve my problem.

The changes should be made here:

[JsonInheritanceConverter(typeof({{ ClassName }}), "{{ Discriminator }}")]

@marinasundstrom
Copy link
Author

My sample project:

https://github.com/marinasundstrom/NullabilityTransformersPrototype/tree/main/WebApi

The Microsoft Open API API doesn't handle inheritance that well, at the moment.

@marinasundstrom
Copy link
Author

marinasundstrom commented Oct 26, 2024

Some background:

I have been working to make the Open API stack in .NET 9 to work with NSwag client generator the way I expect it to. So I have been talking about its output, because I have tried to create a transformer for dealing with inheritance. Open API in .NET has polymorphism but it is not like in NSwag that deals with type hierarchies.

Just assume that I have been hacking Open API specifications.

I have found that if I, in the base schema/type, set additionalProperties: false then the multiple Discriminators (Species) don't show up. That was lacking in my hack.

Indeed, I checked, NSwag outputs that additionalProperties: false.

It is still a difference in how System.Text.Json deals with it.

That makes me wonder whether additionalProperties: false really should make such i difference in NJsonSchema. It should be assumed to be false by default?

@RicoSuter
Copy link
Owner

RicoSuter commented Nov 19, 2024

Should now be possible with the new option:
#1675

@Jozzle
Copy link

Jozzle commented Nov 27, 2024

@RicoSuter

Thanks a lot for addressing this PolymorphicSerialization issue. For some reason the new setting is not recognized when used as a parameter in the .csproj file?

We are on .Net 8 and use the following command in the .proj file:
<Exec WorkingDirectory="$(ProjectDir)" EnvironmentVariables="ASPNETCORE_ENVIRONMENT=Development" Command="$(NSwagExe_Net80) openapi2cscontroller /input:Controllers/specs/openapi-0.1.yaml /classname:Server0_1 /namespace:[REDACTED].PublicApi.Controllers /output:Controllers/generated/ServerController0_1.g.cs /ControllerBaseClass:Microsoft.AspNetCore.Mvc.ControllerBase /JsonLibrary:SystemTextJson /ControllerStyle:abstract /UseActionResultType:true /JsonPolymorphicSerializationStyle:SystemTextJson" />

Error thrown:
3>NSwag bin directory: [REDACTED]nuget\nswag.msbuild\14.2.0\tools\Net80 3>NConsole.UnusedArgumentException: **Unrecognised arguments are present: [/JsonPolymorphicSerializationStyle:SystemTextJson]** 3> at NConsole.CommandLineProcessor.ProcessSingleAsync(String[] args, Object input) 3> at NConsole.CommandLineProcessor.ProcessAsync(String[] args, Object input) 3> at NSwag.Commands.NSwagCommandProcessor.ProcessAsync(String[] args) in /_/src/NSwag.Commands/NSwagCommandProcessor.cs:line 65 3>[REDACTED].PublicApi.csproj(42,9): error MSB3073: The command "dotnet "D:\packages\nuget\nswag.msbuild\14.2.0\buildTransitive\../tools/Net80/dotnet-nswag.dll" openapi2cscontroller /input:Controllers/specs/openapi-0.1.yaml /classname:Server0_1 /namespace:[REDACTED].PublicApi.Controllers /output:Controllers/generated/ServerController0_1.g.cs /ControllerBaseClass:Microsoft.AspNetCore.Mvc.ControllerBase /JsonLibrary:SystemTextJson /ControllerStyle:abstract /UseActionResultType:true /JsonPolymorphicSerializationStyle:SystemTextJson" exited with code -1. 3>Done building project "[REDACTED].PublicApi.csproj" -- FAILED.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants