Skip to content

Commit 45f833b

Browse files
Copilotalexaka1
andcommitted
fix: handle double/float/decimal enums correctly in JSON converters
For floating-point enums (double, float, decimal), C# enums can't have non-integral underlying types, so: - ToJsonValue now returns actual enum values via switch-case instead of casting (which gave wrong values like 2.0 instead of -1.2) - Read method uses reader.GetDouble() etc. and converts to string with InvariantCulture for matching via FromStringOrDefault - Write method uses WriteNumberValue with the corrected ToJsonValue Integer enums (int32, int64) still use direct cast as before. Co-authored-by: alexaka1 <22166651+alexaka1@users.noreply.github.com>
1 parent 29ce4b6 commit 45f833b

77 files changed

Lines changed: 617 additions & 35 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

modules/openapi-generator/src/main/resources/csharp/modelEnum.mustache

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,39 @@
9191
{{>visibility}} static {{>EnumValueDataType}} ToJsonValue({{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} value)
9292
{
9393
{{^isString}}
94+
{{^isFloat}}{{^isDouble}}{{^isDecimal}}
9495
return ({{>EnumValueDataType}}) value;
96+
{{/isDecimal}}{{/isDouble}}{{/isFloat}}
97+
{{#isFloat}}
98+
{{#allowableValues}}
99+
{{#enumVars}}
100+
if (value == {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.{{name}})
101+
return {{{value}}}f;
102+
103+
{{/enumVars}}
104+
{{/allowableValues}}
105+
throw new NotImplementedException($"Value could not be handled: '{value}'");
106+
{{/isFloat}}
107+
{{#isDouble}}
108+
{{#allowableValues}}
109+
{{#enumVars}}
110+
if (value == {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.{{name}})
111+
return {{{value}}}d;
112+
113+
{{/enumVars}}
114+
{{/allowableValues}}
115+
throw new NotImplementedException($"Value could not be handled: '{value}'");
116+
{{/isDouble}}
117+
{{#isDecimal}}
118+
{{#allowableValues}}
119+
{{#enumVars}}
120+
if (value == {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.{{name}})
121+
return {{{value}}}m;
122+
123+
{{/enumVars}}
124+
{{/allowableValues}}
125+
throw new NotImplementedException($"Value could not be handled: '{value}'");
126+
{{/isDecimal}}
95127
{{/isString}}
96128
{{#isString}}
97129
{{#allowableValues}}
@@ -122,9 +154,32 @@
122154
public override {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
123155
{
124156
{{^isString}}
157+
{{^isFloat}}{{^isDouble}}{{^isDecimal}}
125158
{{>EnumValueDataType}} rawValue = reader.{{>EnumJsonReaderMethod}}();
126159
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} result = ({{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}})rawValue;
127160
return result;
161+
{{/isDecimal}}{{/isDouble}}{{/isFloat}}
162+
{{#isFloat}}
163+
string rawValue = reader.GetSingle().ToString(System.Globalization.CultureInfo.InvariantCulture);
164+
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}? result = {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}ValueConverter.FromStringOrDefault(rawValue);
165+
if (result != null)
166+
return result.Value;
167+
throw new JsonException();
168+
{{/isFloat}}
169+
{{#isDouble}}
170+
string rawValue = reader.GetDouble().ToString(System.Globalization.CultureInfo.InvariantCulture);
171+
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}? result = {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}ValueConverter.FromStringOrDefault(rawValue);
172+
if (result != null)
173+
return result.Value;
174+
throw new JsonException();
175+
{{/isDouble}}
176+
{{#isDecimal}}
177+
string rawValue = reader.GetDecimal().ToString(System.Globalization.CultureInfo.InvariantCulture);
178+
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}? result = {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}ValueConverter.FromStringOrDefault(rawValue);
179+
if (result != null)
180+
return result.Value;
181+
throw new JsonException();
182+
{{/isDecimal}}
128183
{{/isString}}
129184
{{#isString}}
130185
string{{nrt?}} rawValue = reader.GetString();
@@ -175,9 +230,32 @@
175230
if (reader.TokenType == JsonTokenType.Null)
176231
return null;
177232

233+
{{^isFloat}}{{^isDouble}}{{^isDecimal}}
178234
{{>EnumValueDataType}} rawValue = reader.{{>EnumJsonReaderMethod}}();
179235
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} result = ({{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}})rawValue;
180236
return result;
237+
{{/isDecimal}}{{/isDouble}}{{/isFloat}}
238+
{{#isFloat}}
239+
string rawValue = reader.GetSingle().ToString(System.Globalization.CultureInfo.InvariantCulture);
240+
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}? result = {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}ValueConverter.FromStringOrDefault(rawValue);
241+
if (result != null)
242+
return result.Value;
243+
throw new JsonException();
244+
{{/isFloat}}
245+
{{#isDouble}}
246+
string rawValue = reader.GetDouble().ToString(System.Globalization.CultureInfo.InvariantCulture);
247+
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}? result = {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}ValueConverter.FromStringOrDefault(rawValue);
248+
if (result != null)
249+
return result.Value;
250+
throw new JsonException();
251+
{{/isDouble}}
252+
{{#isDecimal}}
253+
string rawValue = reader.GetDecimal().ToString(System.Globalization.CultureInfo.InvariantCulture);
254+
{{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}? result = {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}ValueConverter.FromStringOrDefault(rawValue);
255+
if (result != null)
256+
return result.Value;
257+
throw new JsonException();
258+
{{/isDecimal}}
181259
{{/isString}}
182260
{{#isString}}
183261
string{{nrt?}} rawValue = reader.GetString();

modules/openapi-generator/src/test/java/org/openapitools/codegen/csharpnetcore/CSharpClientCodegenTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,5 +309,24 @@ public void testIntegerEnumJsonConverterUsesNumericOperations() throws IOExcepti
309309
"reader.GetString()",
310310
"writer.WriteStringValue("
311311
);
312+
313+
// Verify double enum reads numeric value and converts to string for matching, writes as number
314+
File doubleEnumFile = files.get(Paths
315+
.get(output.getAbsolutePath(), "src", "Org.OpenAPITools", "Model", "DoubleEnum.cs")
316+
.toString()
317+
);
318+
assertNotNull(doubleEnumFile, "Could not find file for model: DoubleEnum");
319+
assertFileContains(doubleEnumFile.toPath(),
320+
"reader.GetDouble().ToString(System.Globalization.CultureInfo.InvariantCulture)",
321+
"writer.WriteNumberValue(",
322+
"public static double ToJsonValue(DoubleEnum value)",
323+
"return 1.1d;",
324+
"return -1.2d;"
325+
);
326+
assertFileNotContains(doubleEnumFile.toPath(),
327+
"reader.GetString()",
328+
"writer.WriteStringValue(",
329+
"return (double) value"
330+
);
312331
}
313332
}

modules/openapi-generator/src/test/resources/3_0/csharp/integer-enum.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,9 @@ components:
3535
x-enum-varnames:
3636
- None
3737
- Some
38+
DoubleEnum:
39+
enum:
40+
- 1.1
41+
- -1.2
42+
type: number
43+
format: double

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/EnumTestEnumInteger.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ public static EnumTestEnumInteger FromString(string value)
8585
/// <exception cref="NotImplementedException"></exception>
8686
public static int ToJsonValue(EnumTestEnumInteger value)
8787
{
88+
8889
return (int) value;
90+
8991
}
9092
}
9193

@@ -104,9 +106,11 @@ public class EnumTestEnumIntegerJsonConverter : JsonConverter<EnumTestEnumIntege
104106
/// <returns></returns>
105107
public override EnumTestEnumInteger Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106108
{
109+
107110
int rawValue = reader.GetInt32();
108111
EnumTestEnumInteger result = (EnumTestEnumInteger)rawValue;
109112
return result;
113+
110114
}
111115

112116
/// <summary>
@@ -138,9 +142,11 @@ public class EnumTestEnumIntegerNullableJsonConverter : JsonConverter<EnumTestEn
138142
if (reader.TokenType == JsonTokenType.Null)
139143
return null;
140144

145+
141146
int rawValue = reader.GetInt32();
142147
EnumTestEnumInteger result = (EnumTestEnumInteger)rawValue;
143148
return result;
149+
144150
}
145151

146152
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/EnumTestEnumIntegerOnly.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ public static EnumTestEnumIntegerOnly FromString(string value)
8585
/// <exception cref="NotImplementedException"></exception>
8686
public static int ToJsonValue(EnumTestEnumIntegerOnly value)
8787
{
88+
8889
return (int) value;
90+
8991
}
9092
}
9193

@@ -104,9 +106,11 @@ public class EnumTestEnumIntegerOnlyJsonConverter : JsonConverter<EnumTestEnumIn
104106
/// <returns></returns>
105107
public override EnumTestEnumIntegerOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106108
{
109+
107110
int rawValue = reader.GetInt32();
108111
EnumTestEnumIntegerOnly result = (EnumTestEnumIntegerOnly)rawValue;
109112
return result;
113+
110114
}
111115

112116
/// <summary>
@@ -138,9 +142,11 @@ public class EnumTestEnumIntegerOnlyNullableJsonConverter : JsonConverter<EnumTe
138142
if (reader.TokenType == JsonTokenType.Null)
139143
return null;
140144

145+
141146
int rawValue = reader.GetInt32();
142147
EnumTestEnumIntegerOnly result = (EnumTestEnumIntegerOnly)rawValue;
143148
return result;
149+
144150
}
145151

146152
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/OuterEnumInteger.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ public static OuterEnumInteger FromString(string value)
9696
/// <exception cref="NotImplementedException"></exception>
9797
public static int ToJsonValue(OuterEnumInteger value)
9898
{
99+
99100
return (int) value;
101+
100102
}
101103
}
102104

@@ -115,9 +117,11 @@ public class OuterEnumIntegerJsonConverter : JsonConverter<OuterEnumInteger>
115117
/// <returns></returns>
116118
public override OuterEnumInteger Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
117119
{
120+
118121
int rawValue = reader.GetInt32();
119122
OuterEnumInteger result = (OuterEnumInteger)rawValue;
120123
return result;
124+
121125
}
122126

123127
/// <summary>
@@ -149,9 +153,11 @@ public class OuterEnumIntegerNullableJsonConverter : JsonConverter<OuterEnumInte
149153
if (reader.TokenType == JsonTokenType.Null)
150154
return null;
151155

156+
152157
int rawValue = reader.GetInt32();
153158
OuterEnumInteger result = (OuterEnumInteger)rawValue;
154159
return result;
160+
155161
}
156162

157163
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/OuterEnumIntegerDefaultValue.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ public static OuterEnumIntegerDefaultValue FromString(string value)
9696
/// <exception cref="NotImplementedException"></exception>
9797
public static int ToJsonValue(OuterEnumIntegerDefaultValue value)
9898
{
99+
99100
return (int) value;
101+
100102
}
101103
}
102104

@@ -115,9 +117,11 @@ public class OuterEnumIntegerDefaultValueJsonConverter : JsonConverter<OuterEnum
115117
/// <returns></returns>
116118
public override OuterEnumIntegerDefaultValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
117119
{
120+
118121
int rawValue = reader.GetInt32();
119122
OuterEnumIntegerDefaultValue result = (OuterEnumIntegerDefaultValue)rawValue;
120123
return result;
124+
121125
}
122126

123127
/// <summary>
@@ -149,9 +153,11 @@ public class OuterEnumIntegerDefaultValueNullableJsonConverter : JsonConverter<O
149153
if (reader.TokenType == JsonTokenType.Null)
150154
return null;
151155

156+
152157
int rawValue = reader.GetInt32();
153158
OuterEnumIntegerDefaultValue result = (OuterEnumIntegerDefaultValue)rawValue;
154159
return result;
160+
155161
}
156162

157163
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/RequiredClassRequiredNotnullableEnumInteger.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ public static RequiredClassRequiredNotnullableEnumInteger FromString(string valu
8585
/// <exception cref="NotImplementedException"></exception>
8686
public static int ToJsonValue(RequiredClassRequiredNotnullableEnumInteger value)
8787
{
88+
8889
return (int) value;
90+
8991
}
9092
}
9193

@@ -104,9 +106,11 @@ public class RequiredClassRequiredNotnullableEnumIntegerJsonConverter : JsonConv
104106
/// <returns></returns>
105107
public override RequiredClassRequiredNotnullableEnumInteger Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106108
{
109+
107110
int rawValue = reader.GetInt32();
108111
RequiredClassRequiredNotnullableEnumInteger result = (RequiredClassRequiredNotnullableEnumInteger)rawValue;
109112
return result;
113+
110114
}
111115

112116
/// <summary>
@@ -138,9 +142,11 @@ public class RequiredClassRequiredNotnullableEnumIntegerNullableJsonConverter :
138142
if (reader.TokenType == JsonTokenType.Null)
139143
return null;
140144

145+
141146
int rawValue = reader.GetInt32();
142147
RequiredClassRequiredNotnullableEnumInteger result = (RequiredClassRequiredNotnullableEnumInteger)rawValue;
143148
return result;
149+
144150
}
145151

146152
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/RequiredClassRequiredNotnullableEnumIntegerOnly.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ public static RequiredClassRequiredNotnullableEnumIntegerOnly FromString(string
8585
/// <exception cref="NotImplementedException"></exception>
8686
public static int ToJsonValue(RequiredClassRequiredNotnullableEnumIntegerOnly value)
8787
{
88+
8889
return (int) value;
90+
8991
}
9092
}
9193

@@ -104,9 +106,11 @@ public class RequiredClassRequiredNotnullableEnumIntegerOnlyJsonConverter : Json
104106
/// <returns></returns>
105107
public override RequiredClassRequiredNotnullableEnumIntegerOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106108
{
109+
107110
int rawValue = reader.GetInt32();
108111
RequiredClassRequiredNotnullableEnumIntegerOnly result = (RequiredClassRequiredNotnullableEnumIntegerOnly)rawValue;
109112
return result;
113+
110114
}
111115

112116
/// <summary>
@@ -138,9 +142,11 @@ public class RequiredClassRequiredNotnullableEnumIntegerOnlyNullableJsonConverte
138142
if (reader.TokenType == JsonTokenType.Null)
139143
return null;
140144

145+
141146
int rawValue = reader.GetInt32();
142147
RequiredClassRequiredNotnullableEnumIntegerOnly result = (RequiredClassRequiredNotnullableEnumIntegerOnly)rawValue;
143148
return result;
149+
144150
}
145151

146152
/// <summary>

samples/client/petstore/csharp/generichost/net10/FormModels/src/Org.OpenAPITools/Model/RequiredClassRequiredNullableEnumInteger.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ public static RequiredClassRequiredNullableEnumInteger FromString(string value)
8585
/// <exception cref="NotImplementedException"></exception>
8686
public static int ToJsonValue(RequiredClassRequiredNullableEnumInteger value)
8787
{
88+
8889
return (int) value;
90+
8991
}
9092
}
9193

@@ -104,9 +106,11 @@ public class RequiredClassRequiredNullableEnumIntegerJsonConverter : JsonConvert
104106
/// <returns></returns>
105107
public override RequiredClassRequiredNullableEnumInteger Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
106108
{
109+
107110
int rawValue = reader.GetInt32();
108111
RequiredClassRequiredNullableEnumInteger result = (RequiredClassRequiredNullableEnumInteger)rawValue;
109112
return result;
113+
110114
}
111115

112116
/// <summary>
@@ -138,9 +142,11 @@ public class RequiredClassRequiredNullableEnumIntegerNullableJsonConverter : Jso
138142
if (reader.TokenType == JsonTokenType.Null)
139143
return null;
140144

145+
141146
int rawValue = reader.GetInt32();
142147
RequiredClassRequiredNullableEnumInteger result = (RequiredClassRequiredNullableEnumInteger)rawValue;
143148
return result;
149+
144150
}
145151

146152
/// <summary>

0 commit comments

Comments
 (0)