Skip to content

Commit 90233d6

Browse files
Ghufzwing328
andauthored
conditional serialization add only those property which user wants to… (#9807)
* conditional serialization add only those property which user wants to configure. * fixed the samples * fixed the sample String to string issue. * fixed the sample String to string issue. * updated the sample * Added unit test for conditional serialization * update samples * remove trailing spaces, update samples * remove files * add back files * build the project in the ci Co-authored-by: William Cheng <wing328hk@gmail.com>
1 parent b9b5394 commit 90233d6

File tree

294 files changed

+39269
-25
lines changed

Some content is hidden

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

294 files changed

+39269
-25
lines changed

appveyor.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ build_script:
5555
- dotnet build samples\client\petstore\csharp-netcore\OpenAPIClient-net47\Org.OpenAPITools.sln
5656
# build C# API client (.net 5.0)
5757
- dotnet build samples\client\petstore\csharp-netcore\OpenAPIClient-net5.0\Org.OpenAPITools.sln
58+
# build C# API client (.net 5.0 with ConditionalSerialization)
59+
- dotnet build samples\client\petstore\csharp-netcore\OpenAPIClient-ConditionalSerialization\Org.OpenAPITools.sln
5860
# build C# API client
5961
- nuget restore samples\client\petstore\csharp\OpenAPIClient\Org.OpenAPITools.sln
6062
- msbuild samples\client\petstore\csharp\OpenAPIClient\Org.OpenAPITools.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
@@ -80,6 +82,8 @@ test_script:
8082
- dotnet test samples\client\petstore\csharp-netcore\OpenAPIClient-net47\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj
8183
# test C# API client (.net 5.0)
8284
- dotnet test samples\client\petstore\csharp-netcore\OpenAPIClient-net5.0\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj
85+
# test C# API Client using conditional-serialization
86+
- dotnet test samples\client\petstore\csharp-netcore\OpenAPIClient-ConditionalSerialization\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj
8387
# test c# API client
8488
- nunit3-console samples\client\petstore\csharp\OpenAPIClient\src\Org.OpenAPITools.Test\bin\Debug\Org.OpenAPITools.Test.dll --result=myresults.xml;format=AppVeyor
8589
# test c# API client (with PropertyChanged)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# for .net standard
2+
generatorName: csharp-netcore
3+
outputDir: samples/client/petstore/csharp-netcore/OpenAPIClient-ConditionalSerialization
4+
inputSpec: modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml
5+
templateDir: modules/openapi-generator/src/main/resources/csharp-netcore
6+
additionalProperties:
7+
packageGuid: '{fa96c953-af24-457d-8a01-f2fd2a7547a9}'
8+
useCompareNetObjects: true
9+
disallowAdditionalPropertiesIfNotPresent: false
10+
useOneOfDiscriminatorLookup: true
11+
targetFramework: netstandard2.0
12+
conditionalSerialization: true

docs/generators/csharp-netcore.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
99
| ------ | ----------- | ------ | ------- |
1010
|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
1111
|caseInsensitiveResponseHeaders|Make API response's headers case-insensitive| |false|
12+
|conditionalSerialization|Serialize only those properties which are initialized by user, accepted values are true or false, default value is false.| |false|
1213
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
1314
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true|
1415
|interfacePrefix|Prefix interfaces with a community standard or widely accepted prefix.| |I|

modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ public class CodegenConstants {
184184
public static final String OPTIONAL_EMIT_DEFAULT_VALUES = "optionalEmitDefaultValues";
185185
public static final String OPTIONAL_EMIT_DEFAULT_VALUES_DESC = "Set DataMember's EmitDefaultValue.";
186186

187+
public static final String OPTIONAL_CONDITIONAL_SERIALIZATION = "conditionalSerialization";
188+
public static final String OPTIONAL_CONDITIONAL_SERIALIZATION_DESC = "Serialize only those properties which are initialized by user, accepted values are true or false, default value is false.";
189+
187190
public static final String NETCORE_PROJECT_FILE = "netCoreProjectFile";
188191
public static final String NETCORE_PROJECT_FILE_DESC = "Use the new format (.NET Core) for .NET project files (.csproj).";
189192

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
4141

4242
protected boolean optionalAssemblyInfoFlag = true;
4343
protected boolean optionalEmitDefaultValuesFlag = false;
44+
protected boolean conditionalSerialization = false;
4445
protected boolean optionalProjectFileFlag = true;
4546
protected boolean optionalMethodArgumentFlag = true;
4647
protected boolean useDateTimeOffsetFlag = false;

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpNetCoreClientCodegen.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@ public CSharpNetCoreClientCodegen() {
265265
addSwitch(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES,
266266
CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES_DESC,
267267
this.optionalEmitDefaultValuesFlag);
268+
269+
addSwitch(CodegenConstants.OPTIONAL_CONDITIONAL_SERIALIZATION,
270+
CodegenConstants.OPTIONAL_CONDITIONAL_SERIALIZATION_DESC,
271+
this.conditionalSerialization);
268272

269273
addSwitch(CodegenConstants.OPTIONAL_PROJECT_FILE,
270274
CodegenConstants.OPTIONAL_PROJECT_FILE_DESC,
@@ -570,6 +574,12 @@ public void processOpts() {
570574
additionalProperties.put(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES, optionalEmitDefaultValuesFlag);
571575
}
572576

577+
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_CONDITIONAL_SERIALIZATION)) {
578+
setConditionalSerialization(convertPropertyToBooleanAndWriteBack(CodegenConstants.OPTIONAL_CONDITIONAL_SERIALIZATION));
579+
} else {
580+
additionalProperties.put(CodegenConstants.OPTIONAL_CONDITIONAL_SERIALIZATION, conditionalSerialization);
581+
}
582+
573583
if (additionalProperties.containsKey(CodegenConstants.MODEL_PROPERTY_NAMING)) {
574584
setModelPropertyNaming((String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
575585
}
@@ -759,6 +769,10 @@ public void setOptionalEmitDefaultValuesFlag(boolean flag) {
759769
this.optionalEmitDefaultValuesFlag = flag;
760770
}
761771

772+
public void setConditionalSerialization(boolean flag){
773+
this.conditionalSerialization = flag;
774+
}
775+
762776
public void setOptionalProjectFileFlag(boolean flag) {
763777
this.optionalProjectFileFlag = flag;
764778
}

modules/openapi-generator/src/main/resources/csharp-netcore/modelGeneric.mustache

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
{{#description}}
3232
/// <value>{{description}}</value>
3333
{{/description}}
34+
{{^conditionalSerialization}}
3435
[DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = {{#vendorExtensions.x-emit-default-value}}true{{/vendorExtensions.x-emit-default-value}}{{^vendorExtensions.x-emit-default-value}}{{#isBoolean}}true{{/isBoolean}}{{^isBoolean}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/isBoolean}}{{/vendorExtensions.x-emit-default-value}})]
3536
public {{#complexType}}{{{complexType}}}{{/complexType}}{{^complexType}}{{{datatypeWithEnum}}}{{/complexType}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}} {{name}} { get; set; }
3637
{{#isReadOnly}}
@@ -44,6 +45,47 @@
4445
return false;
4546
}
4647
{{/isReadOnly}}
48+
{{/conditionalSerialization}}
49+
{{#conditionalSerialization}}
50+
{{#isReadOnly}}
51+
[DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = {{#vendorExtensions.x-emit-default-value}}true{{/vendorExtensions.x-emit-default-value}}{{^vendorExtensions.x-emit-default-value}}{{#isBoolean}}true{{/isBoolean}}{{^isBoolean}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/isBoolean}}{{/vendorExtensions.x-emit-default-value}})]
52+
public {{#complexType}}{{{complexType}}}{{/complexType}}{{^complexType}}{{{datatypeWithEnum}}}{{/complexType}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}} {{name}} { get; set; }
53+
54+
55+
/// <summary>
56+
/// Returns false as {{name}} should not be serialized given that it's read-only.
57+
/// </summary>
58+
/// <returns>false (boolean)</returns>
59+
public bool ShouldSerialize{{name}}()
60+
{
61+
return false;
62+
}
63+
{{/isReadOnly}}
64+
65+
{{^isReadOnly}}
66+
[DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = {{#vendorExtensions.x-emit-default-value}}true{{/vendorExtensions.x-emit-default-value}}{{^vendorExtensions.x-emit-default-value}}{{#isBoolean}}true{{/isBoolean}}{{^isBoolean}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/isBoolean}}{{/vendorExtensions.x-emit-default-value}})]
67+
public {{#complexType}}{{{complexType}}}{{/complexType}}{{^complexType}}{{{datatypeWithEnum}}}{{/complexType}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}} {{name}}
68+
{
69+
get{ return _{{name}};}
70+
set
71+
{
72+
_{{name}} = value;
73+
_flag{{name}} = true;
74+
}
75+
}
76+
private {{#complexType}}{{{complexType}}}{{/complexType}}{{^complexType}}{{{datatypeWithEnum}}}{{/complexType}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}} _{{name}};
77+
private bool _flag{{name}};
78+
79+
/// <summary>
80+
/// Returns false as {{name}} should not be serialized given that it's read-only.
81+
/// </summary>
82+
/// <returns>false (boolean)</returns>
83+
public bool ShouldSerialize{{name}}()
84+
{
85+
return _flag{{name}};
86+
}
87+
{{/isReadOnly}}
88+
{{/conditionalSerialization}}
4789
{{/isEnum}}
4890
{{/vars}}
4991
{{#hasRequired}}
@@ -78,13 +120,24 @@
78120
{{^isInherited}}
79121
{{^isReadOnly}}
80122
{{#required}}
123+
{{^conditionalSerialization}}
81124
{{^vendorExtensions.x-csharp-value-type}}
82125
// to ensure "{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}" is required (not null)
83126
this.{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} ?? throw new ArgumentNullException("{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} is a required property for {{classname}} and cannot be null");
84127
{{/vendorExtensions.x-csharp-value-type}}
85128
{{#vendorExtensions.x-csharp-value-type}}
86129
this.{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}};
87130
{{/vendorExtensions.x-csharp-value-type}}
131+
{{/conditionalSerialization}}
132+
{{#conditionalSerialization}}
133+
{{^vendorExtensions.x-csharp-value-type}}
134+
// to ensure "{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}}" is required (not null)
135+
this._{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} ?? throw new ArgumentNullException("{{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}} is a required property for {{classname}} and cannot be null");
136+
{{/vendorExtensions.x-csharp-value-type}}
137+
{{#vendorExtensions.x-csharp-value-type}}
138+
this._{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}};
139+
{{/vendorExtensions.x-csharp-value-type}}
140+
{{/conditionalSerialization}}
88141
{{/required}}
89142
{{/isReadOnly}}
90143
{{/isInherited}}
@@ -103,7 +156,12 @@
103156
{{/vendorExtensions.x-csharp-value-type}}
104157
{{/defaultValue}}
105158
{{^defaultValue}}
159+
{{^conditionalSerialization}}
106160
this.{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}};
161+
{{/conditionalSerialization}}
162+
{{#conditionalSerialization}}
163+
this._{{name}} = {{#lambda.camelcase_param}}{{name}}{{/lambda.camelcase_param}};
164+
{{/conditionalSerialization}}
107165
{{/defaultValue}}
108166
{{/required}}
109167
{{/isReadOnly}}
@@ -121,6 +179,7 @@
121179
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
122180
/// </summary>{{#description}}
123181
/// <value>{{description}}</value>{{/description}}
182+
{{^conditionalSerialization}}
124183
[DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = {{#vendorExtensions.x-emit-default-value}}true{{/vendorExtensions.x-emit-default-value}}{{^vendorExtensions.x-emit-default-value}}{{#isBoolean}}true{{/isBoolean}}{{^isBoolean}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/isBoolean}}{{/vendorExtensions.x-emit-default-value}})]
125184
{{#isDate}}
126185
[JsonConverter(typeof(OpenAPIDateConverter))]
@@ -136,8 +195,52 @@
136195
{
137196
return false;
138197
}
198+
{{/isReadOnly}}
199+
{{/conditionalSerialization}}
200+
{{#conditionalSerialization}}
201+
{{#isReadOnly}}
202+
[DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = {{#vendorExtensions.x-emit-default-value}}true{{/vendorExtensions.x-emit-default-value}}{{^vendorExtensions.x-emit-default-value}}{{#isBoolean}}true{{/isBoolean}}{{^isBoolean}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/isBoolean}}{{/vendorExtensions.x-emit-default-value}})]
203+
{{#isDate}}
204+
[JsonConverter(typeof(OpenAPIDateConverter))]
205+
{{/isDate}}
206+
public {{{dataType}}} {{name}} { get; private set; }
207+
208+
/// <summary>
209+
/// Returns false as {{name}} should not be serialized given that it's read-only.
210+
/// </summary>
211+
/// <returns>false (boolean)</returns>
212+
public bool ShouldSerialize{{name}}()
213+
{
214+
return false;
215+
}
216+
{{/isReadOnly}}
217+
{{^isReadOnly}}
218+
{{#isDate}}
219+
[JsonConverter(typeof(OpenAPIDateConverter))]
220+
{{/isDate}}
221+
[DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = {{#vendorExtensions.x-emit-default-value}}true{{/vendorExtensions.x-emit-default-value}}{{^vendorExtensions.x-emit-default-value}}{{#isBoolean}}true{{/isBoolean}}{{^isBoolean}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/isBoolean}}{{/vendorExtensions.x-emit-default-value}})]
222+
public {{{dataType}}} {{name}}
223+
{
224+
get{ return _{{name}};}
225+
set
226+
{
227+
_{{name}} = value;
228+
_flag{{name}} = true;
229+
}
230+
}
231+
private {{{dataType}}} _{{name}};
232+
private bool _flag{{name}};
139233

234+
/// <summary>
235+
/// Returns false as {{name}} should not be serialized given that it's read-only.
236+
/// </summary>
237+
/// <returns>false (boolean)</returns>
238+
public bool ShouldSerialize{{name}}()
239+
{
240+
return _flag{{name}};
241+
}
140242
{{/isReadOnly}}
243+
{{/conditionalSerialization}}
141244
{{/isEnum}}
142245
{{/isInherited}}
143246
{{/vars}}

0 commit comments

Comments
 (0)