Skip to content

[BUG] [aspnetcore] Unable to set primitive datatypes (with default spec) to the defaults of the primitive data type #10772

@flobuc

Description

@flobuc
Description

If you specify a primitive datatype model property (like boolean or number) with a default value in the OpenAPI Spec, then it is not possible to set this value to the default value of the primitive datatype.
Sounds crazy, and it drives you crazy.
For example if you specify a boolean with the default "true", you are not able to send this boolean to false. Or more confusing, if you specify a number with a default other than 0 (e.g. 12) then you can't send this number to 0 (all other values are working).

openapi-generator version

5.x and also 6.0.x

generators

aspnetcore , maybe also other C# generators (csharp, csharp-netcore)

OpenAPI declaration
components:
  schemas:
    TESTOBJECT:
      type: object
        properties:
          TESTPROP1:
            type: boolean
            description: a boolean with default true
            default: true
          TESTPROP2:
            type: number
            format: int32
            description: a number with default 12
            default: 12
Generation Details
powershell docker run --rm -v %OUTPUT_DIRECTORY%:/out -v %INTERFACE_DIRECTORY%:/specs openapitools/openapi-generator-cli generate -i specs/%INTERFACE_FILE% -o /out -g aspnetcore --additional-properties aspnetCoreVersion=5.0,buildTarget=library,operationModifier=abstract,packageName=%PACKAGE_NAME%,packageVersion=%INTERFACE_VERSION%,enumValueSuffix=,removeEnumValuePrefix=false
Request-Json
{
    "TESTPROP1": false,
    "TESTPROP2": 0
}
Actual model values
TESTOBJECT {
   TESTPROP1: true
   TESTPROP2: 12
}
Expected model values
TESTOBJECT {
   TESTPROP1: false
   TESTPROP2: 0
}
Suggest a fix

The problem is that the generator is not handling the default values.
Actual generated TESTOBJECT class:

[DataMember(Name="TESTPROP1", EmitDefaultValue=false)]
public bool TESTPROP1{ get; set; } = true;

[DataMember(Name="TESTPROP2", EmitDefaultValue=false)]
public decimal TESTPROP2{ get; set; } = 12;

Per default "EmitDefaultValue=false". So there is no mapping false for TESTPROP1, because false is the default value for a boolean. So it is not possible to set TESTPROP1 to false.
Also 0 is not mapped for TESTPROP2, because 0 is the default value for a decimal.

The fix would be to change modle.mustache to generate:

[DataMember(Name="TESTPROP1", EmitDefaultValue=false)]
[DefaultValue(true)]
public bool TESTPROP1{ get; set; } = true;

[DataMember(Name="TESTPROP2", EmitDefaultValue=false)]
[DefaultValue(12)]
public decimal TESTPROP2{ get; set; } = 12;

So the default-value for the primitive data type is changed, and false and 0 would be mapped.
So far i can test it, it was working with .NET 5.0

Workaround

If it is possible to change the OpenAPI-Spec, then you can also set nullable=true:

components:
  schemas:
    TESTOBJECT:
      type: object
        properties:
          TESTPROP1:
            type: boolean
            description: a boolean with default true
            default: true
            nullable: true
          TESTPROP2:
            type: number
            format: int32
            description: a number with default 12
            default: 12
            nullable: true

With this spec the current 5.x generator generates EmitDefaultValue=true for the properties, so that all values (default or not are always mapped). But this has the drawback, that the generated properties are then nullable:

[DataMember(Name="TESTPROP1", EmitDefaultValue=true)]
public bool? TESTPROP1{ get; set; } = true;

[DataMember(Name="TESTPROP2", EmitDefaultValue=true)]
public decimal? TESTPROP2{ get; set; } = 12;
Related issues/PRs

#3274
#4346
#9071

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions