diff --git a/bin/configs/csharp-generichost-net4.7-formModels.yaml b/bin/configs/csharp-generichost-net4.7-formModels.yaml index fb62b3e616f..6634d259f96 100644 --- a/bin/configs/csharp-generichost-net4.7-formModels.yaml +++ b/bin/configs/csharp-generichost-net4.7-formModels.yaml @@ -12,5 +12,6 @@ additionalProperties: equatable: true targetFramework: net47 skipFormModel: false + modelPropertySorting: alphabetical inlineSchemaOptions: RESOLVE_INLINE_ENUMS: true diff --git a/bin/configs/csharp-generichost-net4.7-useDateTimeForDate.yaml b/bin/configs/csharp-generichost-net4.7-useDateTimeForDate.yaml index df99b81be03..ca299c4849c 100644 --- a/bin/configs/csharp-generichost-net4.7-useDateTimeForDate.yaml +++ b/bin/configs/csharp-generichost-net4.7-useDateTimeForDate.yaml @@ -8,3 +8,4 @@ additionalProperties: packageGuid: '{2E60EF87-DB0B-4D01-A36E-F5E90F7EC757}' useDateTimeForDate: true targetFramework: net47 + modelPropertySorting: alphabetical diff --git a/bin/configs/csharp-generichost-net4.7.yaml b/bin/configs/csharp-generichost-net4.7.yaml index 4ee75448fbc..0eb928f3e2b 100644 --- a/bin/configs/csharp-generichost-net4.7.yaml +++ b/bin/configs/csharp-generichost-net4.7.yaml @@ -11,3 +11,4 @@ additionalProperties: nullableReferenceTypes: false equatable: true targetFramework: net47 + modelPropertySorting: alphabetical diff --git a/bin/configs/csharp-generichost-net4.8-formModels.yaml b/bin/configs/csharp-generichost-net4.8-formModels.yaml index 5617bc8f801..ca16d286f19 100644 --- a/bin/configs/csharp-generichost-net4.8-formModels.yaml +++ b/bin/configs/csharp-generichost-net4.8-formModels.yaml @@ -12,5 +12,6 @@ additionalProperties: equatable: true targetFramework: net48 skipFormModel: false + modelPropertySorting: alphabetical inlineSchemaOptions: RESOLVE_INLINE_ENUMS: true diff --git a/bin/configs/csharp-generichost-net4.8-useDateTimeForDate.yaml b/bin/configs/csharp-generichost-net4.8-useDateTimeForDate.yaml index d8e9842364e..cf88bb71536 100644 --- a/bin/configs/csharp-generichost-net4.8-useDateTimeForDate.yaml +++ b/bin/configs/csharp-generichost-net4.8-useDateTimeForDate.yaml @@ -8,3 +8,4 @@ additionalProperties: packageGuid: '{2E60EF87-DB0B-4D01-A36E-F5E90F7EC757}' useDateTimeForDate: true targetFramework: net48 + modelPropertySorting: alphabetical diff --git a/bin/configs/csharp-generichost-net4.8.yaml b/bin/configs/csharp-generichost-net4.8.yaml index 113eed1a558..8e33e8b54a1 100644 --- a/bin/configs/csharp-generichost-net4.8.yaml +++ b/bin/configs/csharp-generichost-net4.8.yaml @@ -11,3 +11,4 @@ additionalProperties: nullableReferenceTypes: false equatable: true targetFramework: net48 + modelPropertySorting: alphabetical diff --git a/bin/configs/csharp-generichost-net8-formModels.yaml b/bin/configs/csharp-generichost-net8-formModels.yaml index 14f15ca5710..48f677f318c 100644 --- a/bin/configs/csharp-generichost-net8-formModels.yaml +++ b/bin/configs/csharp-generichost-net8-formModels.yaml @@ -12,5 +12,6 @@ additionalProperties: equatable: true targetFramework: net8.0 skipFormModel: false + modelPropertySorting: alphabetical inlineSchemaOptions: RESOLVE_INLINE_ENUMS: true diff --git a/bin/configs/csharp-generichost-net8-nrt-useSourceGeneration.yaml b/bin/configs/csharp-generichost-net8-nrt-useSourceGeneration.yaml index 98c05dd48bc..8901f9cfa9b 100644 --- a/bin/configs/csharp-generichost-net8-nrt-useSourceGeneration.yaml +++ b/bin/configs/csharp-generichost-net8-nrt-useSourceGeneration.yaml @@ -11,3 +11,4 @@ additionalProperties: useSourceGeneration: true equatable: true targetFramework: net8.0 + modelPropertySorting: alphabetical diff --git a/bin/configs/csharp-generichost-net8-nrt.yaml b/bin/configs/csharp-generichost-net8-nrt.yaml index f3e328fff31..c9cccf5f590 100644 --- a/bin/configs/csharp-generichost-net8-nrt.yaml +++ b/bin/configs/csharp-generichost-net8-nrt.yaml @@ -11,3 +11,4 @@ additionalProperties: nullableReferenceTypes: true equatable: true targetFramework: net8.0 + modelPropertySorting: alphabetical diff --git a/bin/configs/csharp-generichost-net8-useDateTimeForDate.yaml b/bin/configs/csharp-generichost-net8-useDateTimeForDate.yaml index 1f986e61afc..72f89ad2f26 100644 --- a/bin/configs/csharp-generichost-net8-useDateTimeForDate.yaml +++ b/bin/configs/csharp-generichost-net8-useDateTimeForDate.yaml @@ -8,3 +8,4 @@ additionalProperties: packageGuid: '{2E60EF87-DB0B-4D01-A36E-F5E90F7EC757}' useDateTimeForDate: true targetFramework: net8.0 + modelPropertySorting: alphabetical diff --git a/bin/configs/csharp-generichost-net8.yaml b/bin/configs/csharp-generichost-net8.yaml index 04870438f3b..790a7bfeb0e 100644 --- a/bin/configs/csharp-generichost-net8.yaml +++ b/bin/configs/csharp-generichost-net8.yaml @@ -11,3 +11,4 @@ additionalProperties: nullableReferenceTypes: false equatable: true targetFramework: net8.0 + modelPropertySorting: alphabetical diff --git a/bin/configs/csharp-generichost-netstandard2.0.yaml b/bin/configs/csharp-generichost-netstandard2.0.yaml index 3450bcc67af..085f4f44276 100644 --- a/bin/configs/csharp-generichost-netstandard2.0.yaml +++ b/bin/configs/csharp-generichost-netstandard2.0.yaml @@ -10,3 +10,4 @@ additionalProperties: disallowAdditionalPropertiesIfNotPresent: false targetFramework: netstandard2.0 equatable: true + modelPropertySorting: alphabetical diff --git a/docs/generators/csharp.md b/docs/generators/csharp.md index 2ba8b33b13a..8e6cd6abb7d 100644 --- a/docs/generators/csharp.md +++ b/docs/generators/csharp.md @@ -31,6 +31,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |library|HTTP library template (sub-template) to use|
**generichost**
HttpClient with Generic Host dependency injection (https://docs.microsoft.com/en-us/dotnet/core/extensions/generic-host) (Experimental. Subject to breaking changes without notice.)
**httpclient**
HttpClient (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) (Experimental. Subject to breaking changes without notice.)
**unityWebRequest**
UnityWebRequest (...) (Experimental. Subject to breaking changes without notice.)
**restsharp**
RestSharp (https://github.com/restsharp/RestSharp)
|restsharp| |licenseId|The identifier of the license| |null| |modelPropertyNaming|Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name| |PascalCase| +|modelPropertySorting|One of legacy, alphabetical, default (only `generichost` library supports this option).| |legacy| |netCoreProjectFile|Use the new format (.NET Core) for .NET project files (.csproj).| |false| |nonPublicApi|Generates code with reduced access modifiers; allows embedding elsewhere without exposing non-public API calls to consumers.| |false| |nullableReferenceTypes|Use nullable annotations in the project. Only supported on C# 8 / ASP.NET Core 3.1 or newer. Starting in .NET 6.0 the default is true.| |false| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java index b1d801d3cb6..8a30d47575f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java @@ -119,12 +119,14 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { protected boolean nonPublicApi = Boolean.FALSE; private static final String OPERATION_PARAMETER_SORTING_KEY = "operationParameterSorting"; + private static final String MODEL_PROPERTY_SORTING_KEY = "modelPropertySorting"; enum SortingMethod { DEFAULT, ALPHABETICAL, LEGACY } private SortingMethod operationParameterSorting = SortingMethod.LEGACY; + private SortingMethod modelPropertySorting = SortingMethod.LEGACY; protected boolean caseInsensitiveResponseHeaders = Boolean.FALSE; protected String releaseNote = "Minor update"; @@ -230,6 +232,10 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { "One of legacy, alphabetical, default (only `generichost` library supports this option).", this.operationParameterSorting.toString().toLowerCase(Locale.ROOT)); + addOption(CSharpClientCodegen.MODEL_PROPERTY_SORTING_KEY, + "One of legacy, alphabetical, default (only `generichost` library supports this option).", + this.modelPropertySorting.toString().toLowerCase(Locale.ROOT)); + CliOption framework = new CliOption( CodegenConstants.DOTNET_FRAMEWORK, CodegenConstants.DOTNET_FRAMEWORK_DESC @@ -465,21 +471,42 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { // avoid breaking changes if (GENERICHOST.equals(getLibrary()) && codegenModel != null) { - Collections.sort(codegenModel.vars, propertyComparatorByName); - Collections.sort(codegenModel.allVars, propertyComparatorByName); - Collections.sort(codegenModel.requiredVars, propertyComparatorByName); - Collections.sort(codegenModel.optionalVars, propertyComparatorByName); - Collections.sort(codegenModel.readOnlyVars, propertyComparatorByName); - Collections.sort(codegenModel.readWriteVars, propertyComparatorByName); - Collections.sort(codegenModel.parentVars, propertyComparatorByName); + if (this.modelPropertySorting == SortingMethod.LEGACY) { + Collections.sort(codegenModel.vars, propertyComparatorByName); + Collections.sort(codegenModel.allVars, propertyComparatorByName); + Collections.sort(codegenModel.requiredVars, propertyComparatorByName); + Collections.sort(codegenModel.optionalVars, propertyComparatorByName); + Collections.sort(codegenModel.readOnlyVars, propertyComparatorByName); + Collections.sort(codegenModel.readWriteVars, propertyComparatorByName); + Collections.sort(codegenModel.parentVars, propertyComparatorByName); - Collections.sort(codegenModel.vars, propertyComparatorByNotNullableRequiredNoDefault); - Collections.sort(codegenModel.allVars, propertyComparatorByNotNullableRequiredNoDefault); - Collections.sort(codegenModel.requiredVars, propertyComparatorByNotNullableRequiredNoDefault); - Collections.sort(codegenModel.optionalVars, propertyComparatorByNotNullableRequiredNoDefault); - Collections.sort(codegenModel.readOnlyVars, propertyComparatorByNotNullableRequiredNoDefault); - Collections.sort(codegenModel.readWriteVars, propertyComparatorByNotNullableRequiredNoDefault); - Collections.sort(codegenModel.parentVars, propertyComparatorByNotNullableRequiredNoDefault); + Collections.sort(codegenModel.vars, propertyComparatorByNotNullableRequiredNoDefaultLegacy); + Collections.sort(codegenModel.allVars, propertyComparatorByNotNullableRequiredNoDefaultLegacy); + Collections.sort(codegenModel.requiredVars, propertyComparatorByNotNullableRequiredNoDefaultLegacy); + Collections.sort(codegenModel.optionalVars, propertyComparatorByNotNullableRequiredNoDefaultLegacy); + Collections.sort(codegenModel.readOnlyVars, propertyComparatorByNotNullableRequiredNoDefaultLegacy); + Collections.sort(codegenModel.readWriteVars, propertyComparatorByNotNullableRequiredNoDefaultLegacy); + Collections.sort(codegenModel.parentVars, propertyComparatorByNotNullableRequiredNoDefaultLegacy); + } + else { + if (this.modelPropertySorting == SortingMethod.ALPHABETICAL) { + Collections.sort(codegenModel.vars, propertyComparatorByName); + Collections.sort(codegenModel.allVars, propertyComparatorByName); + Collections.sort(codegenModel.requiredVars, propertyComparatorByName); + Collections.sort(codegenModel.optionalVars, propertyComparatorByName); + Collections.sort(codegenModel.readOnlyVars, propertyComparatorByName); + Collections.sort(codegenModel.readWriteVars, propertyComparatorByName); + Collections.sort(codegenModel.parentVars, propertyComparatorByName); + } + + Collections.sort(codegenModel.vars, propertyComparatorByNotNullableRequiredNoDefault); + Collections.sort(codegenModel.allVars, propertyComparatorByNotNullableRequiredNoDefault); + Collections.sort(codegenModel.requiredVars, propertyComparatorByNotNullableRequiredNoDefault); + Collections.sort(codegenModel.optionalVars, propertyComparatorByNotNullableRequiredNoDefault); + Collections.sort(codegenModel.readOnlyVars, propertyComparatorByNotNullableRequiredNoDefault); + Collections.sort(codegenModel.readWriteVars, propertyComparatorByNotNullableRequiredNoDefault); + Collections.sort(codegenModel.parentVars, propertyComparatorByNotNullableRequiredNoDefault); + } } return codegenModel; @@ -492,6 +519,18 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { } }; + public static Comparator propertyComparatorByNotNullableRequiredNoDefaultLegacy = new Comparator() { + @Override + public int compare(CodegenProperty one, CodegenProperty another) { + if (one.isNullable == another.isNullable && one.required == another.required && (one.defaultValue == null) == (another.defaultValue == null)) + return 0; + else if (!one.isNullable && one.required && one.defaultValue == null) + return -1; + else + return 1; + } + }; + public static Comparator propertyComparatorByNotNullableRequiredNoDefault = Comparator.comparing(p -> p.isNullable || !p.required || p.defaultValue != null); @@ -686,6 +725,10 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { setOperationParameterSorting((String) additionalProperties.get(CSharpClientCodegen.OPERATION_PARAMETER_SORTING_KEY)); } + if (additionalProperties.containsKey(CSharpClientCodegen.MODEL_PROPERTY_SORTING_KEY)) { + setModelPropertySorting((String) additionalProperties.get(CSharpClientCodegen.MODEL_PROPERTY_SORTING_KEY)); + } + if (additionalProperties.containsKey(CodegenConstants.API_NAME)) { setApiName((String) additionalProperties.get(CodegenConstants.API_NAME)); } else { @@ -1123,6 +1166,14 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { this.operationParameterSorting = SortingMethod.valueOf(operationParameterSorting.toUpperCase(Locale.ROOT)); } + public void setModelPropertySorting(String modelPropertySorting) { + if (modelPropertySorting == null) { + modelPropertySorting = "DEFAULT"; + } + + this.modelPropertySorting = SortingMethod.valueOf(modelPropertySorting.toUpperCase(Locale.ROOT)); + } + public void setSupportsAsync(Boolean supportsAsync) { this.supportsAsync = supportsAsync; }