From 0de216ffed67b68219c965ab35024e85a121836f Mon Sep 17 00:00:00 2001 From: devhl Date: Mon, 21 Jul 2025 19:10:40 -0400 Subject: [PATCH 1/3] started fixing multiple issues --- .../languages/AbstractCSharpCodegen.java | 100 +++++++++++++++--- .../generichost/JsonConverter.mustache | 15 +-- .../generichost/modelGeneric.mustache | 10 +- 3 files changed, 97 insertions(+), 28 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java index 84c47521f1d0..db5262ee22fd 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java @@ -629,7 +629,7 @@ public Map postProcessAllModels(Map objs) List allOf = composedSchemas.getAllOf(); if (allOf != null) { for (CodegenProperty property : allOf) { - property.name = patchPropertyName(model, camelize(property.baseType), composedPropertyNames); + property.name = patchPropertyName(model, property, camelize(property.baseType), composedPropertyNames); patchPropertyVendorExtensions(property); } } @@ -638,7 +638,7 @@ public Map postProcessAllModels(Map objs) if (anyOf != null) { removePropertiesDeclaredInComposedTypes(objs, model, anyOf); for (CodegenProperty property : anyOf) { - property.name = patchPropertyName(model, camelize(property.baseType), composedPropertyNames); + property.name = patchPropertyName(model, property, camelize(property.baseType), composedPropertyNames); property.isNullable = true; patchPropertyVendorExtensions(property); property.vendorExtensions.put("x-base-name", model.name.substring(model.name.lastIndexOf('_') + 1)); @@ -649,10 +649,18 @@ public Map postProcessAllModels(Map objs) if (oneOf != null) { removePropertiesDeclaredInComposedTypes(objs, model, oneOf); for (CodegenProperty property : oneOf) { - property.name = patchPropertyName(model, camelize(property.baseType), composedPropertyNames); + property.name = patchPropertyName(model, property, camelize(property.baseType), composedPropertyNames); property.isNullable = true; patchPropertyVendorExtensions(property); property.vendorExtensions.put("x-base-name", model.name.substring(model.name.lastIndexOf('_') + 1)); + + if (!property.isEnum) { + CodegenModel composedOf = ModelUtils.getModelByName(property.name, processed); + if (composedOf != null) { + property.isEnum = composedOf.isEnum; + patchPropertyVendorExtensions(property); + } + } } } } @@ -716,7 +724,47 @@ private boolean modelIsMutable(CodegenModel model, Set processed) { protected void removePropertiesDeclaredInComposedTypes(Map objs, CodegenModel model, List composedProperties) { } - private String patchPropertyName(CodegenModel model, String value, Set composedPropertyNames) { + /** + * If the model has duplicate proprety names, just make it unique + * This can happen for base names like "id" and "@id" + * @param model + * @param property + * @param value + * @return + */ + private String setUniquePropertyName(CodegenModel model, CodegenProperty property, String value) { + if (property.name.equalsIgnoreCase(property.baseName)) { + return value; + } + + Optional alreadyUpdatedProperty = model.allVars.stream() + .filter(p -> !p.name.equals(property.name) && p.baseName.equals(property.baseName)) + .collect(Collectors.toList()) + .stream() + .findFirst(); + + if (alreadyUpdatedProperty.isPresent()) { + // above iterates allVars, which may have already been corrected + return alreadyUpdatedProperty.get().name; + } + + final String tmp = value; + + long count = model.allVars.stream() + .filter(v -> v.name.equalsIgnoreCase(tmp)) + .count(); + + if (count > 1) { + value = value + count; + value = setUniquePropertyName(model, property, value); + } + + return value; + } + + private String patchPropertyName(CodegenModel model, CodegenProperty property, String value, Set composedPropertyNames) { + value = setUniquePropertyName(model, property, value); + String name = escapeReservedWord(model, value); if (name.startsWith(AbstractCSharpCodegen.invalidParameterNamePrefix)) { @@ -768,26 +816,44 @@ protected void patchProperty(Map enumRefs, CodegenModel mo patchPropertyVendorExtensions(property); - property.name = patchPropertyName(model, property.name, null); + property.name = patchPropertyName(model, property, property.name, null); + + patchNestedMaps(property); + + // HOTFIX: https://github.com/OpenAPITools/openapi-generator/issues/14944 + if (property.datatypeWithEnum.equals("decimal")) { + property.isDecimal = true; + } + } + + private void patchNestedMaps(CodegenProperty property) { + // Process nested types before making any replacements to ensure we have the correct inner type + if (property.items != null) { + patchNestedMaps(property.items); + } String[] nestedTypes = {"List", "Collection", "ICollection", "Dictionary"}; + + if (property.datatypeWithEnum != null) { + String originalType = property.datatypeWithEnum; + + for (String nestedType : nestedTypes) { + // fix incorrect data types for maps of maps + if (property.items != null) { + if (property.datatypeWithEnum.contains(", " + nestedType + ">")) { + property.datatypeWithEnum = property.datatypeWithEnum.replace(", " + nestedType + ">", ", " + property.items.datatypeWithEnum + ">"); + } - Arrays.stream(nestedTypes).forEach(nestedType -> { - // fix incorrect data types for maps of maps - if (property.datatypeWithEnum.contains(", " + nestedType + ">") && property.items != null) { - property.datatypeWithEnum = property.datatypeWithEnum.replace(", " + nestedType + ">", ", " + property.items.datatypeWithEnum + ">"); - property.dataType = property.datatypeWithEnum; + if (property.datatypeWithEnum.contains("<" + nestedType + ">")) { + property.datatypeWithEnum = property.datatypeWithEnum.replace("<" + nestedType + ">", "<" + property.items.datatypeWithEnum + ">"); + } + } } - if (property.datatypeWithEnum.contains("<" + nestedType + ">") && property.items != null) { - property.datatypeWithEnum = property.datatypeWithEnum.replace("<" + nestedType + ">", "<" + property.items.datatypeWithEnum + ">"); + // Only update dataType if we actually made changes + if (!originalType.equals(property.datatypeWithEnum)) { property.dataType = property.datatypeWithEnum; } - }); - - // HOTFIX: https://github.com/OpenAPITools/openapi-generator/issues/14944 - if (property.datatypeWithEnum.equals("decimal")) { - property.isDecimal = true; } } diff --git a/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/JsonConverter.mustache b/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/JsonConverter.mustache index a416373c9dea..ae4eb632a5e9 100644 --- a/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/JsonConverter.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/JsonConverter.mustache @@ -287,7 +287,7 @@ {{^model.composedSchemas.anyOf}} {{#mappedModels}} if ({{#lambda.camelcase_sanitize_param}}{{model.classname}}{{/lambda.camelcase_sanitize_param}} != null) - return new {{classname}}({{#lambda.joinWithComma}}{{#lambda.camelcase_sanitize_param}}{{model.classname}}{{/lambda.camelcase_sanitize_param}}{{#vendorExtensions.x-is-value-type}}{{^isNullable}}.Value{{/isNullable}}{{/vendorExtensions.x-is-value-type}} {{#model.composedSchemas.anyOf}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#vendorExtensions.x-is-value-type}}{{^isNullable}}.Value{{/isNullable}}{{/vendorExtensions.x-is-value-type}} {{/model.composedSchemas.anyOf}}{{#allVars}}{{^isDiscriminator}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#required}}.Value{{nrt!}}{{^isNullable}}{{#vendorExtensions.x-is-value-type}}.Value{{/vendorExtensions.x-is-value-type}}{{/isNullable}}{{/required}} {{/isDiscriminator}}{{/allVars}}{{/lambda.joinWithComma}}); + return new {{classname}}({{#lambda.joinWithComma}}{{#lambda.camelcase_sanitize_param}}{{model.classname}}{{/lambda.camelcase_sanitize_param}}{{#vendorExtensions.x-is-value-type}}{{^isNullable}}.Value{{/isNullable}}{{/vendorExtensions.x-is-value-type}} {{#model.composedSchemas.anyOf}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#vendorExtensions.x-is-value-type}}{{^isNullable}}.Value{{/isNullable}}{{/vendorExtensions.x-is-value-type}} {{/model.composedSchemas.anyOf}}{{#allVars}}{{^isDiscriminator}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#required}}.Value{{nrt!}}{{^isNullable}}{{#vendorExtensions.x-is-value-type}}.Value{{/vendorExtensions.x-is-value-type}}{{/isNullable}}{{/required}} {{/isDiscriminator}}{{/allVars}}{{/lambda.joinWithComma}}); // a {{#-last}} throw new JsonException(); @@ -299,22 +299,22 @@ {{^composedSchemas.oneOf}} {{^required}} {{#model.composedSchemas.anyOf}} - Option<{{baseType}}{{>NullConditionalProperty}}> {{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}ParsedValue = {{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}} == null + Option<{{{datatypeWithEnum}}}{{>NullConditionalProperty}}> {{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}ParsedValue = {{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}} == null ? default - : new Option<{{baseType}}{{>NullConditionalProperty}}>({{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}); + : new Option<{{{datatypeWithEnum}}}{{>NullConditionalProperty}}>({{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}); {{/model.composedSchemas.anyOf}} {{#-last}} {{/-last}} {{/required}} - return new {{classname}}({{#lambda.joinWithComma}}{{#model.composedSchemas.anyOf}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}ParsedValue{{#required}}.Value{{#vendorExtensions.x-is-value-type}}{{nrt!}}.Value{{nrt!}}{{/vendorExtensions.x-is-value-type}}{{/required}} {{/model.composedSchemas.anyOf}}{{#allVars}}{{^isDiscriminator}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#required}}.Value{{nrt!}}{{^isNullable}}{{#vendorExtensions.x-is-value-type}}.Value{{nrt!}}{{/vendorExtensions.x-is-value-type}}{{/isNullable}}{{/required}} {{/isDiscriminator}}{{/allVars}}{{/lambda.joinWithComma}}); + return new {{classname}}({{#lambda.joinWithComma}}{{#model.composedSchemas.anyOf}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}ParsedValue{{#required}}.Value{{#vendorExtensions.x-is-value-type}}{{nrt!}}.Value{{nrt!}}{{/vendorExtensions.x-is-value-type}}{{/required}} {{/model.composedSchemas.anyOf}}{{#allVars}}{{^isDiscriminator}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#required}}.Value{{nrt!}}{{^isNullable}}{{#vendorExtensions.x-is-value-type}}.Value{{nrt!}}{{/vendorExtensions.x-is-value-type}}{{/isNullable}}{{/required}} {{/isDiscriminator}}{{/allVars}}{{/lambda.joinWithComma}}); // b {{/composedSchemas.oneOf}} {{^model.discriminator}} {{#composedSchemas}} {{#oneOf}} {{^vendorExtensions.x-duplicated-data-type}} if ({{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}} != null) - return new {{classname}}({{#lambda.joinWithComma}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#vendorExtensions.x-is-value-type}}.Value{{/vendorExtensions.x-is-value-type}} {{#model.composedSchemas.anyOf}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#vendorExtensions.x-is-value-type}}{{^isNullable}}.Value{{/isNullable}}{{/vendorExtensions.x-is-value-type}} {{/model.composedSchemas.anyOf}}{{#allVars}}{{^isDiscriminator}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#required}}ParsedValue{{/required}} {{/isDiscriminator}}{{/allVars}}{{/lambda.joinWithComma}}); + return new {{classname}}({{#lambda.joinWithComma}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#vendorExtensions.x-is-value-type}}.Value{{/vendorExtensions.x-is-value-type}}/**{{isEnum}}**/ {{#model.composedSchemas.anyOf}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#vendorExtensions.x-is-value-type}}{{^isNullable}}.Value{{/isNullable}}{{/vendorExtensions.x-is-value-type}} {{/model.composedSchemas.anyOf}}{{#allVars}}{{^isDiscriminator}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{#required}}ParsedValue{{/required}} {{/isDiscriminator}}{{/allVars}}{{/lambda.joinWithComma}}); // c {{/vendorExtensions.x-duplicated-data-type}} {{#-last}} @@ -337,6 +337,7 @@ /// public override void Write(Utf8JsonWriter writer, {{classname}} {{#lambda.camelcase_sanitize_param}}{{classname}}{{/lambda.camelcase_sanitize_param}}, JsonSerializerOptions jsonSerializerOptions) { + // b {{#lambda.trimLineBreaks}} {{#lambda.copyText}} {{#lambda.camelcase_sanitize_param}}{{classname}}{{/lambda.camelcase_sanitize_param}} @@ -397,7 +398,7 @@ {{^isPrimitiveType}} { {{datatypeWithEnum}}JsonConverter {{datatypeWithEnum}}JsonConverter = ({{datatypeWithEnum}}JsonConverter) jsonSerializerOptions.Converters.First(c => c.CanConvert({{#lambda.camelcase_sanitize_param}}{{model.classname}}{{/lambda.camelcase_sanitize_param}}.{{name}}{{^required}}Option.Value{{/required}}.GetType())); - {{datatypeWithEnum}}JsonConverter.WriteProperties(writer, {{#lambda.camelcase_sanitize_param}}{{model.classname}}{{/lambda.camelcase_sanitize_param}}.{{name}}{{^required}}Option.Value{{/required}}, jsonSerializerOptions); + {{datatypeWithEnum}}JsonConverter.WriteProperties(writer, {{#lambda.camelcase_sanitize_param}}{{model.classname}}{{/lambda.camelcase_sanitize_param}}.{{name}}{{^required}}Option.Value{{/required}}, jsonSerializerOptions); //here {{isEnum}} } {{/isPrimitiveType}} @@ -407,8 +408,10 @@ WriteProperties(writer, {{#lambda.camelcase_sanitize_param}}{{classname}}{{/lambda.camelcase_sanitize_param}}, jsonSerializerOptions); writer.WriteEndObject(); {{/lambda.trimLineBreaks}} + // hi } +// a /// /// Serializes the properties of /// diff --git a/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/modelGeneric.mustache b/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/modelGeneric.mustache index 587057cddd32..c6be37ba756e 100644 --- a/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/modelGeneric.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/modelGeneric.mustache @@ -17,20 +17,20 @@ /// {{description}}{{^description}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/description}}{{#defaultValue}} (default to {{.}}){{/defaultValue}} {{/isDiscriminator}} {{/allVars}} - {{#model.vendorExtensions.x-model-is-mutable}}{{>visibility}}{{/model.vendorExtensions.x-model-is-mutable}}{{^model.vendorExtensions.x-model-is-mutable}}internal{{/model.vendorExtensions.x-model-is-mutable}} {{classname}}({{#lambda.joinWithComma}}{{{dataType}}} {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}} {{#model.composedSchemas.anyOf}}{{^required}}Option<{{/required}}{{{dataType}}}{{>NullConditionalProperty}}{{^required}}>{{/required}} {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{baseType}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}} {{/model.composedSchemas.anyOf}}{{>ModelSignature}}{{/lambda.joinWithComma}}){{#parent}} : base({{#lambda.joinWithComma}}{{#parentModel.composedSchemas.oneOf}}{{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{parent}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}}.{{#lambda.titlecase}}{{baseType}}{{/lambda.titlecase}} {{/parentModel.composedSchemas.oneOf}}{{>ModelBaseSignature}}{{/lambda.joinWithComma}}){{/parent}} + {{#model.vendorExtensions.x-model-is-mutable}}{{>visibility}}{{/model.vendorExtensions.x-model-is-mutable}}{{^model.vendorExtensions.x-model-is-mutable}}internal{{/model.vendorExtensions.x-model-is-mutable}} {{classname}}(/**a**/{{#lambda.joinWithComma}}{{{dataType}}} {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}} {{#model.composedSchemas.anyOf}}{{^required}}Option<{{/required}}{{{dataType}}}{{>NullConditionalProperty}}{{^required}}>{{/required}} {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{baseType}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}} {{/model.composedSchemas.anyOf}}{{>ModelSignature}}{{/lambda.joinWithComma}}){{#parent}} : base({{#lambda.joinWithComma}}{{#parentModel.composedSchemas.oneOf}}{{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{parent}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}}.{{#lambda.titlecase}}{{baseType}}{{/lambda.titlecase}} {{/parentModel.composedSchemas.oneOf}}{{>ModelBaseSignature}}{{/lambda.joinWithComma}}){{/parent}} { {{#composedSchemas.anyOf}} - {{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}{{^required}}Option{{/required}} = {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}}; + {{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}{{^required}}Option{{/required}} = {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}}; // a1 {{dataType}} {{/composedSchemas.anyOf}} {{name}} = {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}}; {{#allVars}} {{^isDiscriminator}} {{^isInherited}} - {{name}}{{^required}}Option{{/required}} = {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}}; + {{name}}{{^required}}Option{{/required}} = {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}}; // a2 {{dataType}} {{/isInherited}} {{#isInherited}} {{#isNew}} - {{name}}{{^required}}Option{{/required}} = {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}}; + {{name}}{{^required}}Option{{/required}} = {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}}; // a3 {{dataType}} {{/isNew}} {{/isInherited}} {{/isDiscriminator}} @@ -62,7 +62,7 @@ {{^composedSchemas.anyOf}} [JsonConstructor] {{/composedSchemas.anyOf}} - {{#model.vendorExtensions.x-model-is-mutable}}{{>visibility}}{{/model.vendorExtensions.x-model-is-mutable}}{{^model.vendorExtensions.x-model-is-mutable}}internal{{/model.vendorExtensions.x-model-is-mutable}} {{classname}}({{#lambda.joinWithComma}}{{#composedSchemas.anyOf}}{{^required}}Option<{{/required}}{{{baseType}}}{{>NullConditionalProperty}}{{^required}}>{{/required}} {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}} {{/composedSchemas.anyOf}}{{>ModelSignature}}{{/lambda.joinWithComma}}){{#parent}} : base({{#lambda.joinWithComma}}{{>ModelBaseSignature}}{{/lambda.joinWithComma}}){{/parent}} + {{#model.vendorExtensions.x-model-is-mutable}}{{>visibility}}{{/model.vendorExtensions.x-model-is-mutable}}{{^model.vendorExtensions.x-model-is-mutable}}internal{{/model.vendorExtensions.x-model-is-mutable}} {{classname}}(/**b**/{{#lambda.joinWithComma}}{{#composedSchemas.anyOf}}{{^required}}Option<{{/required}}{{{datatypeWithEnum}}}/**{{dataType}}**/{{>NullConditionalProperty}}{{^required}}>{{/required}} {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}} {{/composedSchemas.anyOf}}{{>ModelSignature}}{{/lambda.joinWithComma}}){{#parent}} : base({{#lambda.joinWithComma}}{{>ModelBaseSignature}}{{/lambda.joinWithComma}}){{/parent}} { {{#composedSchemas.anyOf}} {{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}{{^required}}Option{{/required}} = {{#lambda.escape_reserved_word}}{{#lambda.camel_case}}{{name}}{{/lambda.camel_case}}{{/lambda.escape_reserved_word}}; From be1a19504cdc5824f14ae59837addf3f8229fba9 Mon Sep 17 00:00:00 2001 From: devhl Date: Sat, 26 Jul 2025 15:48:35 -0400 Subject: [PATCH 2/3] weather api builds --- .../csharp/libraries/generichost/JsonConverter.mustache | 3 ++- .../resources/csharp/libraries/generichost/api_test.mustache | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/JsonConverter.mustache b/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/JsonConverter.mustache index ae4eb632a5e9..71407be2b7c6 100644 --- a/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/JsonConverter.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/JsonConverter.mustache @@ -398,7 +398,8 @@ {{^isPrimitiveType}} { {{datatypeWithEnum}}JsonConverter {{datatypeWithEnum}}JsonConverter = ({{datatypeWithEnum}}JsonConverter) jsonSerializerOptions.Converters.First(c => c.CanConvert({{#lambda.camelcase_sanitize_param}}{{model.classname}}{{/lambda.camelcase_sanitize_param}}.{{name}}{{^required}}Option.Value{{/required}}.GetType())); - {{datatypeWithEnum}}JsonConverter.WriteProperties(writer, {{#lambda.camelcase_sanitize_param}}{{model.classname}}{{/lambda.camelcase_sanitize_param}}.{{name}}{{^required}}Option.Value{{/required}}, jsonSerializerOptions); //here {{isEnum}} + {{datatypeWithEnum}}JsonConverter.Write{{^isEnumRef}}Properties{{/isEnumRef}}(writer, {{#lambda.camelcase_sanitize_param}}{{model.classname}}{{/lambda.camelcase_sanitize_param}}.{{name}}{{^required}}Option.Value{{#isNullable}}.Value{{/isNullable}}{{/required}}, jsonSerializerOptions); // isEnumRef: {{isEnumRef}} x-is-reference-type: {{vendorExtensions.x-is-reference-type}} isNullable: {{isNullable}} + {{! what if it is an inner enum? }} } {{/isPrimitiveType}} diff --git a/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/api_test.mustache b/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/api_test.mustache index 330b4cc8f800..c1e417bf231e 100644 --- a/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/api_test.mustache +++ b/modules/openapi-generator/src/main/resources/csharp/libraries/generichost/api_test.mustache @@ -39,7 +39,7 @@ namespace {{packageName}}.Test.{{apiPackage}} {{/allParams}} {{#returnType}} var response = await _instance.{{operationId}}Async({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); - var model = response.{{#lambda.first}}{{#responses}}{{vendorExtensions.x-http-status}} {{/responses}}{{/lambda.first}}(); + var model = response.{{#lambda.first}}{{#responses}}{{#dataType}}{{vendorExtensions.x-http-status}} {{/dataType}}{{/responses}}{{/lambda.first}}(); Assert.IsType<{{{.}}}>(model); {{/returnType}} {{^returnType}} From f94d8ce8d847552ab76c9361bbbed463b3cef1a3 Mon Sep 17 00:00:00 2001 From: devhl Date: Mon, 28 Jul 2025 21:58:05 -0400 Subject: [PATCH 3/3] added docstring --- .../languages/AbstractCSharpCodegen.java | 35 +++---------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java index adeab769e85a..19dfd1bb120d 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java @@ -762,6 +762,10 @@ private String setUniquePropertyName(CodegenModel model, CodegenProperty propert return value; } + /** + * Fixes nested maps so the generic type is defined + * Convertes List> to List> + */ private String patchPropertyName(CodegenModel model, CodegenProperty property, String value, Set composedPropertyNames) { value = setUniquePropertyName(model, property, value); @@ -857,37 +861,6 @@ protected void patchProperty(Map enumRefs, CodegenModel mo } } - private void patchNestedMaps(CodegenProperty property) { - // Process nested types before making any replacements to ensure we have the correct inner type - if (property.items != null) { - patchNestedMaps(property.items); - } - - String[] nestedTypes = {"List", "Collection", "ICollection", "Dictionary"}; - - if (property.datatypeWithEnum != null) { - String originalType = property.datatypeWithEnum; - - for (String nestedType : nestedTypes) { - // fix incorrect data types for maps of maps - if (property.items != null) { - if (property.datatypeWithEnum.contains(", " + nestedType + ">")) { - property.datatypeWithEnum = property.datatypeWithEnum.replace(", " + nestedType + ">", ", " + property.items.datatypeWithEnum + ">"); - } - - if (property.datatypeWithEnum.contains("<" + nestedType + ">")) { - property.datatypeWithEnum = property.datatypeWithEnum.replace("<" + nestedType + ">", "<" + property.items.datatypeWithEnum + ">"); - } - } - } - - // Only update dataType if we actually made changes - if (!originalType.equals(property.datatypeWithEnum)) { - property.dataType = property.datatypeWithEnum; - } - } - } - @Override protected List> buildEnumVars(List values, String dataType) { List> enumVars = super.buildEnumVars(values, dataType);