C# decimal default literal doesn't compile
Created by: wheezil
A field of type "number" with no format is mapped to decimal/Decimal types in various languages. However, the utility method ModelUtils.IsDouble() incorrectly reports true. This leads to cases where e.g. generated C# code creates fields of type decimal but tries to initialize them with default values that are double-formatted literals ("0.1D") instead of decimal-format literals ("0.1M"). Code does not compile.
Description
Bug in ModelUtils.isDoubleSchema makes C# codegen produce incorrect literals, and probably affects other languages.
openapi-generator version
3.3.2
OpenAPI declaration file content or url
Any schema with field declaration of number without format, and with a default value e.g.:
{
"openapi": "3.0.0",
"info": {
"description": "blah",
"version": "1.0.0",
"title": "blah"
},
"paths": {
},
"components": {
"requestBodies": {
},
"schemas": {
"Part": {
"properties": {
"cost":{
"type": "number",
"default":"0.0"
}
}
}
}
}
}
Command line used for generation
Specifically the csharp generator has problems, but probably any language that maps number to a "decimal" type will have difficulties because it cannot distinguish double from "other number"
generate -g csharp ...
Steps to reproduce
Run generation with csharp laugnage option. Note that generated Cost field is of type decimal:
public decimal? Cost { get; set; }
But default initializer doesn't compile:
public Part(decimal? cost = 0.0D)
{
// use default value if no "cost" provided
if (cost == null)
{
this.Cost = 0.0D;
}
The literal would need to be 0.0M
not 0.0D
. This looks like a bug in AbstractCSharpCodegen, which formats the literal as 0.0D
instead of 0.0M
:
public String toDefaultValue(Schema p) {
...
} else if (ModelUtils.isNumberSchema(p)) {
if (p.getDefault() != null) {
if (ModelUtils.isFloatSchema(p)) { // float
return p.getDefault().toString() + "F";
} else if (ModelUtils.isDoubleSchema(p)) { // double
return p.getDefault().toString() + "D";
} else {
return p.getDefault().toString();
}
}
The method ModelUtils.isDoubleSchema(p)
incorrectly returns true, making C# codegen produce the wrong default literal.
However... even if this were fixed, the C# codegen is still wrong, because it needs to add "M" to the decimal literal:
...
return p.getDefault().toString() + "M";
Related issues/PRs
Suggest a fix/enhancement
In this method
public static boolean isDoubleSchema(Schema schema) {
if (schema instanceof NumberSchema) {
return true;
}
if (SchemaTypeUtil.NUMBER_TYPE.equals(schema.getType())
&& SchemaTypeUtil.DOUBLE_FORMAT.equals(schema.getFormat())) { // format: double
return true;
}
return false;
}
These lines should be removed:
if (schema instanceof NumberSchema) {
return true;
}
And in AbstractCSharpCodegen.toDefaultValue(Schema p)
, return the correct decimal literal in default case:
public String toDefaultValue(Schema p) {
...
} else if (ModelUtils.isNumberSchema(p)) {
...
} else {
return p.getDefault().toString() + "M";
}
}