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

[Required] attribute not applied to generated C# int properties #5111

Open
ChristophHornung opened this issue Feb 24, 2025 · 2 comments
Open

Comments

@ChristophHornung
Copy link

Describe the bug

Generating the code for

{
  "swagger": "2.0",
  "info": {
    "title": "Swagger specification",
    "version": "1.0.0"
  },
  "paths": {
    "/Product": {
      "get": {
        "operationId": "Product",
        "responses": {
          "200": {
            "description": "",
            "schema": {
              "$ref": "#/definitions/Product"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "Product": {
      "type": "object",
      "required": [
        "Id",
        "StringId"
      ],
      "properties": {
        "Id": {
          "type": "integer",
          "format": "int32"
        },
        "StringId": {
          "type": "string",
          "minLength": 1
        }
      }
    }
  }
}

via (e.g.)

var settings = new CSharpClientGeneratorSettings();
settings.CSharpGeneratorSettings.JsonLibrary = NJsonSchema.CodeGeneration.CSharp.CSharpJsonLibrary.SystemTextJson;
settings.CSharpGeneratorSettings.JsonSerializerSettingsTransformationMethod = "TestJsonSerializerSettingsTransformationMethod";

var generator = new CSharpClientGenerator(document, settings);

Generates a C# class of

[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.2.0.0 (NJsonSchema v11.1.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class Product
    {

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

        [System.Text.Json.Serialization.JsonPropertyName("StringId")]
        [System.ComponentModel.DataAnnotations.Required]
        public string StringId { get; set; }

    }

I would have expected for the Id property to retain a Required attribute as well. Or am I missing something here?

Version used

14.2.0

@roeldewit
Copy link

The Required attribute checks if the property is not null, a integer can't be null so the Required attribute is redundant. If you want the integer value to be in a specific range you can use the Range attribute for validation or you could make the integer nullable if that's what you're looking for.

@ChristophHornung
Copy link
Author

@roeldewit The Required attribute is not synonymous with not null as they are two different concepts. It is true that in C# the concept of "required" is weaker than in other languages but that is exactly what the attribute is for.
But especially in the context of OpenAPI this distinction matters.

That is why

public class Product
{
	[Required]
	public int Id { get; set; }
}

with the the JsonSchemaGenerator will generate

"definitions": {
    "Product": {
      "type": "object",
      "required": [
        "Id"
      ],
      "properties": {
        "Id": {
          "type": "integer",
          "format": "int32"
        }
      }
    }
  }

while

public class Product
{
	public int Id { get; set; }
}

will generate

"Product": {
      "type": "object",
      "properties": {
        "Id": {
          "type": "integer",
          "format": "int32"
        }
      }
    }

So why after a simple roundtrip with NSwag from C# class to openapi.json back to C# class is this information lost?

E.g. when simply using the generated class in an API that also generates an OpenAPI suddenly the definitions would look different.

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

2 participants