From 618f4bdd39ce740edca75fa2e9db93656d54ca33 Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Sat, 7 May 2016 22:22:48 -0400 Subject: [PATCH] [csharp] Constructor handling for serialization Resolving an issue with serializing classes that contain required properties. When the only constructor has defaulted parameters, no parameterless constructor is generated but JSON.Net attempts to call the missing constructor on deserialization (because of DataContract). See: https://manski.net/2014/10/net-serializers-comparison-chart/ The fix here is to create a protected constructor, annotate it with JsonConstructorAttribute to inform JSON.Net it is the constructor to use during serialization, then provide settings that explicitly allow JSON.Net to access non-public constructors during serialiazation. --- .../src/main/java/io/swagger/codegen/CodegenModel.java | 2 +- .../src/main/java/io/swagger/codegen/DefaultCodegen.java | 2 ++ .../src/main/resources/csharp/ApiClient.mustache | 7 ++++++- .../src/main/resources/csharp/modelGeneric.mustache | 7 +++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenModel.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenModel.java index ccea2ee070e9..438eb1912946 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenModel.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenModel.java @@ -27,7 +27,7 @@ public class CodegenModel { public Set allMandatory; public Set imports = new TreeSet(); - public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum; + public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum, hasRequired; public ExternalDocs externalDocs; public Map vendorExtensions; diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java index db000e9c63ed..abe9dbea04ef 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java @@ -2432,6 +2432,7 @@ public class DefaultCodegen { private void addVars(CodegenModel m, Map properties, List required, Map allProperties, List allRequired) { + m.hasRequired = false; if (properties != null && !properties.isEmpty()) { m.hasVars = true; m.hasEnums = false; @@ -2470,6 +2471,7 @@ public class DefaultCodegen { } else { final CodegenProperty cp = fromProperty(key, prop); cp.required = mandatory.contains(key) ? true : null; + m.hasRequired = Boolean.TRUE.equals(m.hasRequired) || Boolean.TRUE.equals(cp.required); if (cp.isEnum) { // FIXME: if supporting inheritance, when called a second time for allProperties it is possible for // m.hasEnums to be set incorrectly if allProperties has enumerations but properties does not. diff --git a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache index 2c0f8f681e38..f9b9f7662999 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache @@ -20,6 +20,11 @@ namespace {{packageName}}.Client /// public class ApiClient { + private JsonSerializerSettings serializerSettings = new JsonSerializerSettings + { + ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor + }; + /// /// Initializes a new instance of the class /// with default configuration and base path ({{basePath}}). @@ -305,7 +310,7 @@ namespace {{packageName}}.Client // at this point, it must be a model (json) try { - return JsonConvert.DeserializeObject(response.Content, type); + return JsonConvert.DeserializeObject(response.Content, type, serializerSettings); } catch (Exception e) { diff --git a/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache b/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache index 6c5da5e4f56b..ebadaf2046ae 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache @@ -24,6 +24,13 @@ public {{{datatypeWithEnum}}}{{#isEnum}}?{{/isEnum}} {{name}} { get; set; } {{/isEnum}} {{/vars}} + {{#hasRequired}} + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected {{classname}}() { } + {{/hasRequired}} /// /// Initializes a new instance of the class. ///