RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.67k stars 1.23k forks source link

Generated C# client has errors, when using classes with virtual members and class style record #4752

Open nonwombatant opened 6 months ago

nonwombatant commented 6 months ago

Given the following classes

    public class Foo
    {
        public virtual int Number { get; set; }
    }

    public class Bar : Foo
    {
        public override int Number { get; set; }
    }

The following is generated in the swagger document

      "Foo": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "number": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "Bar": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Foo"
          },
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "number": {
                "type": "integer",
                "format": "int32"
              }
            }
          }
        ]
      },

And when generating a C# client using the "classStyle": "Record" you get the following

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.2.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
    public partial class Foo
    {
        [System.Text.Json.Serialization.JsonConstructor]

        public Foo(int @number)

        {

            this.Number = @number;

        }
        [System.Text.Json.Serialization.JsonPropertyName("number")]
        public int Number { get; }

    }

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.2.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
    public partial class Bar : Foo
    {
        [System.Text.Json.Serialization.JsonConstructor]

        public Bar(int @number, int @number)

            : base(number)

        {

            this.Number = @number;

        }
        [System.Text.Json.Serialization.JsonPropertyName("number")]
        public int Number { get; }

    }

or with "generateNativeRecords": true

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.2.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
    public partial record Foo
    {
        [System.Text.Json.Serialization.JsonConstructor]

        public Foo(int @number)

        {

            this.Number = @number;

        }
        [System.Text.Json.Serialization.JsonPropertyName("number")]
        public int Number { get; init; }

    }

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.2.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
    public partial record Bar : Foo
    {
        [System.Text.Json.Serialization.JsonConstructor]

        public Bar(int @number, int @number)

            : base(number)

        {

            this.Number = @number;

        }
        [System.Text.Json.Serialization.JsonPropertyName("number")]
        public int Number { get; init; }

    }

Both Bar constructors generate with a duplicate "number" parameter