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;
}