diff --git a/docs/generators/go-experimental.md b/docs/generators/go-experimental.md index 2f2fed44c40..d5298fd44f1 100644 --- a/docs/generators/go-experimental.md +++ b/docs/generators/go-experimental.md @@ -40,6 +40,8 @@ sidebar_label: go-experimental
  • int
  • int32
  • int64
  • +
  • interface{}
  • +
  • map[string]interface{}
  • rune
  • string
  • uint
  • diff --git a/docs/generators/go-gin-server.md b/docs/generators/go-gin-server.md index 5849d833000..fd8255defdf 100644 --- a/docs/generators/go-gin-server.md +++ b/docs/generators/go-gin-server.md @@ -33,6 +33,8 @@ sidebar_label: go-gin-server
  • int
  • int32
  • int64
  • +
  • interface{}
  • +
  • map[string]interface{}
  • rune
  • string
  • uint
  • diff --git a/docs/generators/go-server.md b/docs/generators/go-server.md index ee435baed9c..462c0d7f6d0 100644 --- a/docs/generators/go-server.md +++ b/docs/generators/go-server.md @@ -36,6 +36,8 @@ sidebar_label: go-server
  • int
  • int32
  • int64
  • +
  • interface{}
  • +
  • map[string]interface{}
  • rune
  • string
  • uint
  • diff --git a/docs/generators/go.md b/docs/generators/go.md index 830a42503de..a2ea935c2cc 100644 --- a/docs/generators/go.md +++ b/docs/generators/go.md @@ -40,6 +40,8 @@ sidebar_label: go
  • int
  • int32
  • int64
  • +
  • interface{}
  • +
  • map[string]interface{}
  • rune
  • string
  • uint
  • diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java index c3257231e28..b6255e1fe02 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenProperty.java @@ -20,12 +20,43 @@ package org.openapitools.codegen; import java.util.*; public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperties { - public String openApiType, baseName, complexType, getter, setter, description, dataType, - datatypeWithEnum, dataFormat, name, min, max, defaultValue, defaultValueWithParam, - baseType, containerType, title; + /** + * The value of the 'type' attribute in the OpenAPI schema. + * The per-language codegen logic may change to a language-specific type. + */ + public String openApiType; + public String baseName; + public String complexType; + public String getter; + public String setter; + /** + * The value of the 'description' attribute in the OpenAPI schema. + */ + public String description; + /** + * The language-specific data type for this property. For example, the OpenAPI type 'integer' + * may be represented as 'int', 'int32', 'Integer', etc, depending on the programming language. + */ + public String dataType; + public String datatypeWithEnum; + public String dataFormat; + /** + * The name of this property in the OpenAPI schema. + */ + public String name; + public String min; // TODO: is this really used? + public String max; // TODO: is this really used? + public String defaultValue; + public String defaultValueWithParam; + public String baseType; + public String containerType; + /** + * The value of the 'title' attribute in the OpenAPI schema. + */ + public String title; /** - * The 'description' string without escape charcters needed by some programming languages/targets + * The 'description' string without escape characters needed by some programming languages/targets */ public String unescapedDescription; @@ -47,10 +78,30 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti public String example; public String jsonSchema; + /** + * The value of the 'minimum' attribute in the OpenAPI schema. + * The value of "minimum" MUST be a number, representing an inclusive lower limit for a numeric instance. + */ public String minimum; + /** + * The value of the 'maximum' attribute in the OpenAPI schema. + * The value of "maximum" MUST be a number, representing an inclusive upper limit for a numeric instance. + */ public String maximum; + /** + * The value of the 'multipleOf' attribute in the OpenAPI schema. + * The value of "multipleOf" MUST be a number, strictly greater than 0. + */ public Number multipleOf; + /** + * The value of the 'exclusiveMinimum' attribute in the OpenAPI schema. + * The value of "exclusiveMinimum" MUST be number, representing an exclusive lower limit for a numeric instance. + */ public boolean exclusiveMinimum; + /** + * The value of the 'exclusiveMaximum' attribute in the OpenAPI schema. + * The value of "exclusiveMaximum" MUST be number, representing an exclusive upper limit for a numeric instance. + */ public boolean exclusiveMaximum; public boolean hasMore; public boolean required; @@ -59,6 +110,12 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti public boolean hasMoreNonReadOnly; // for model constructor, true if next property is not readonly public boolean isPrimitiveType; public boolean isModel; + /** + * True if this property is an array of items or a map container. + * See: + * - ModelUtils.isArraySchema() + * - ModelUtils.isMapSchema() + */ public boolean isContainer; public boolean isString; public boolean isNumeric; @@ -76,7 +133,15 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti public boolean isUuid; public boolean isUri; public boolean isEmail; + /** + * The type is a free-form object, i.e. it is a map of string to values with no declared properties + */ public boolean isFreeFormObject; + /** + * The 'type' in the OAS schema is unspecified (i.e. not set). The value can be number, integer, string, object or array. + * If the nullable attribute is set to true, the 'null' value is valid. + */ + public boolean isAnyType; public boolean isListContainer; public boolean isMapContainer; public boolean isEnum; @@ -621,7 +686,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti exclusiveMaximum == that.exclusiveMaximum && hasMore == that.hasMore && required == that.required && - deprecated == this.deprecated && + deprecated == that.deprecated && secondaryParam == that.secondaryParam && hasMoreNonReadOnly == that.hasMoreNonReadOnly && isPrimitiveType == that.isPrimitiveType && diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 58c897abc5d..6d9f40bf57f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -1945,6 +1945,8 @@ public class DefaultCodegen implements CodegenConfig { } return "string"; } else if (ModelUtils.isFreeFormObject(schema)) { + // Note: the value of a free-form object cannot be an arbitrary type. Per OAS specification, + // it must be a map of string to values. return "object"; } else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) { // having property implies it's a model return "object"; @@ -1952,7 +1954,10 @@ public class DefaultCodegen implements CodegenConfig { LOGGER.warn("Unknown type found in the schema: " + schema.getType()); return schema.getType(); } - + // The 'type' attribute has not been set in the OAS schema, which means the value + // can be an arbitrary type, e.g. integer, string, object, array, number... + // TODO: we should return a different value to distinguish between free-form object + // and arbitrary type. return "object"; } @@ -2707,6 +2712,9 @@ public class DefaultCodegen implements CodegenConfig { setNonArrayMapProperty(property, type); Schema refOrCurrent = ModelUtils.getReferencedSchema(this.openAPI, p); property.isModel = (ModelUtils.isComposedSchema(refOrCurrent) || ModelUtils.isObjectSchema(refOrCurrent)) && ModelUtils.isModel(refOrCurrent); + if (ModelUtils.isAnyTypeSchema(p)) { + property.isAnyType = true; + } } LOGGER.debug("debugging from property return: " + property); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java index ea265d6c24b..d4c0a8514e6 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java @@ -91,7 +91,10 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege "complex64", "complex128", "rune", - "byte") + "byte", + "map[string]interface{}", + "interface{}" + ) ); instantiationTypes.clear(); @@ -116,7 +119,17 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege typeMapping.put("file", "*os.File"); typeMapping.put("binary", "*os.File"); typeMapping.put("ByteArray", "string"); + // A 'type: object' OAS schema without any declared property is + // (per JSON schema specification) "an unordered set of properties + // mapping a string to an instance". + // Hence map[string]interface{} is the proper implementation in golang. + // Note: OpenAPITools uses the same token 'object' for free-form objects + // and arbitrary types. A free form object is implemented in golang as + // map[string]interface{}, whereas an arbitrary type is implemented + // in golang as interface{}. + // See issue #5387 for more details. typeMapping.put("object", "map[string]interface{}"); + typeMapping.put("interface{}", "interface{}"); numberTypes = new HashSet( Arrays.asList( @@ -303,6 +316,12 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege return name; } + /** + * Return the golang implementation type for the specified property. + * + * @param p the OAS property. + * @return the golang implementation type. + */ @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isArraySchema(p)) { @@ -342,6 +361,12 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege return toModelName(openAPIType); } + /** + * Return the OpenAPI type for the property. + * + * @param p the OAS property. + * @return the OpenAPI type. + */ @Override public String getSchemaType(Schema p) { String openAPIType = super.getSchemaType(p); @@ -350,6 +375,9 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege if (ref != null && !ref.isEmpty()) { type = openAPIType; + } else if ("object".equals(openAPIType) && ModelUtils.isAnyTypeSchema(p)) { + // Arbitrary type. Note this is not the same thing as free-form object. + type = "interface{}"; } else if (typeMapping.containsKey(openAPIType)) { type = typeMapping.get(openAPIType); if (languageSpecificPrimitives.contains(type)) @@ -556,6 +584,17 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege } } + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + // The 'go-experimental/model.mustache' template conditionally generates accessor methods. + // For primitive types and custom types (e.g. interface{}, map[string]interface{}...), + // the generated code has a wrapper type and a Get() function to access the underlying type. + // For containers (e.g. Array, Map), the generated code returns the type directly. + if (property.isContainer || property.isFreeFormObject || property.isAnyType) { + property.vendorExtensions.put("x-golang-is-container", true); + } + } + @Override public Map postProcessModels(Map objs) { // remove model imports to avoid error diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientExperimentalCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientExperimentalCodegen.java index 441d199a392..56c63ec0c63 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientExperimentalCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientExperimentalCodegen.java @@ -167,7 +167,8 @@ public class GoClientExperimentalCodegen extends GoClientCodegen { for (CodegenProperty param : model.vars) { param.vendorExtensions.put("x-go-base-type", param.dataType); - if (!param.isNullable || param.isMapContainer || param.isListContainer) { + if (!param.isNullable || param.isMapContainer || param.isListContainer || + param.isFreeFormObject || param.isAnyType) { continue; } if (param.isDateTime) { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index 13265572a93..44373cd8c3b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -636,7 +636,7 @@ public class ModelUtils { } /** - * Check to see if the schema is a model with at least one properties + * Check to see if the schema is a model with at least one property. * * @param schema potentially containing a '$ref' * @return true if it's a model with at least one properties @@ -657,6 +657,42 @@ public class ModelUtils { return schema instanceof ComposedSchema; } + /** + * Return true if the schema value can be any type, i.e. it can be + * the null value, integer, number, string, object or array. + * One use case is when the "type" attribute in the OAS schema is unspecified. + * + * Examples: + * + * arbitraryTypeValue: + * description: This is an arbitrary type schema. + * It is not a free-form object. + * The value can be any type except the 'null' value. + * arbitraryTypeNullableValue: + * description: This is an arbitrary type schema. + * It is not a free-form object. + * The value can be any type, including the 'null' value. + * nullable: true + * + * @param schema the OAS schema. + * @return true if the schema value can be an arbitrary type. + */ + public static boolean isAnyTypeSchema(Schema schema) { + if (schema == null) { + once(LOGGER).error("Schema cannot be null in isAnyTypeSchema check"); + return false; + } + if (schema.getClass().equals(Schema.class) && schema.get$ref() == null && schema.getType() == null && + (schema.getProperties() == null || schema.getProperties().isEmpty()) && + schema.getAdditionalProperties() == null && schema.getNot() == null && + schema.getEnum() == null) { + return true; + // If and when type arrays are supported in a future OAS specification, + // we could return true if the type array includes all possible JSON schema types. + } + return false; + } + /** * Check to see if the schema is a free form object. * @@ -665,6 +701,25 @@ public class ModelUtils { * 2) Is not a composed schema (no anyOf, oneOf, allOf), and * 3) additionalproperties is not defined, or additionalproperties: true, or additionalproperties: {}. * + * Examples: + * + * components: + * schemas: + * arbitraryObject: + * type: object + * description: This is a free-form object. + * The value must be a map of strings to values. The value cannot be 'null'. + * It cannot be array, string, integer, number. + * arbitraryNullableObject: + * type: object + * description: This is a free-form object. + * The value must be a map of strings to values. The value can be 'null', + * It cannot be array, string, integer, number. + * nullable: true + * arbitraryTypeValue: + * description: This is NOT a free-form object. + * The value can be any type except the 'null' value. + * * @param schema potentially containing a '$ref' * @return true if it's a free-form object */ @@ -1361,4 +1416,4 @@ public class ModelUtils { if (maxProperties != null) target.setMaxProperties(maxProperties); } } -} \ No newline at end of file +} diff --git a/modules/openapi-generator/src/main/resources/go-experimental/model.mustache b/modules/openapi-generator/src/main/resources/go-experimental/model.mustache index e1fff60e631..91a0d12b314 100644 --- a/modules/openapi-generator/src/main/resources/go-experimental/model.mustache +++ b/modules/openapi-generator/src/main/resources/go-experimental/model.mustache @@ -69,7 +69,7 @@ func New{{classname}}({{#vars}}{{#required}}{{nameInCamelCase}} {{dataType}}, {{ {{/required}} {{^required}} {{#defaultValue}} -{{^isContainer}} +{{^vendorExtensions.x-golang-is-container}} {{#isNullable}} var {{nameInCamelCase}} {{{datatypeWithEnum}}} = {{{.}}} this.{{name}} = *New{{{dataType}}}(&{{nameInCamelCase}}) @@ -78,7 +78,7 @@ func New{{classname}}({{#vars}}{{#required}}{{nameInCamelCase}} {{dataType}}, {{ var {{nameInCamelCase}} {{{dataType}}} = {{{.}}} this.{{name}} = &{{nameInCamelCase}} {{/isNullable}} -{{/isContainer}} +{{/vendorExtensions.x-golang-is-container}} {{/defaultValue}} {{/required}} {{/vars}} @@ -92,7 +92,7 @@ func New{{classname}}WithDefaults() *{{classname}} { this := {{classname}}{} {{#vars}} {{#defaultValue}} -{{^isContainer}} +{{^vendorExtensions.x-golang-is-container}} {{#isNullable}} {{!we use datatypeWithEnum here, since it will represent the non-nullable name of the datatype, e.g. int64 for NullableInt64}} var {{nameInCamelCase}} {{{datatypeWithEnum}}} = {{{.}}} @@ -102,7 +102,7 @@ func New{{classname}}WithDefaults() *{{classname}} { var {{nameInCamelCase}} {{{dataType}}} = {{{.}}} this.{{name}} = {{^required}}&{{/required}}{{nameInCamelCase}} {{/isNullable}} -{{/isContainer}} +{{/vendorExtensions.x-golang-is-container}} {{/defaultValue}} {{/vars}} return &this @@ -115,18 +115,18 @@ func New{{classname}}WithDefaults() *{{classname}} { // If the value is explicit nil, the zero value for {{vendorExtensions.x-go-base-type}} will be returned {{/isNullable}} func (o *{{classname}}) Get{{name}}() {{vendorExtensions.x-go-base-type}} { - if o == nil {{#isNullable}}{{^isContainer}}|| o.{{name}}.Get() == nil{{/isContainer}}{{/isNullable}} { + if o == nil {{#isNullable}}{{^vendorExtensions.x-golang-is-container}}|| o.{{name}}.Get() == nil{{/vendorExtensions.x-golang-is-container}}{{/isNullable}} { var ret {{vendorExtensions.x-go-base-type}} return ret } {{#isNullable}} -{{#isContainer}} +{{#vendorExtensions.x-golang-is-container}} return o.{{name}} -{{/isContainer}} -{{^isContainer}} +{{/vendorExtensions.x-golang-is-container}} +{{^vendorExtensions.x-golang-is-container}} return *o.{{name}}.Get() -{{/isContainer}} +{{/vendorExtensions.x-golang-is-container}} {{/isNullable}} {{^isNullable}} return o.{{name}} @@ -139,16 +139,16 @@ func (o *{{classname}}) Get{{name}}() {{vendorExtensions.x-go-base-type}} { // NOTE: If the value is an explicit nil, `nil, true` will be returned {{/isNullable}} func (o *{{classname}}) Get{{name}}Ok() (*{{vendorExtensions.x-go-base-type}}, bool) { - if o == nil {{#isNullable}}{{#isContainer}}|| o.{{name}} == nil{{/isContainer}}{{/isNullable}} { + if o == nil {{#isNullable}}{{#vendorExtensions.x-golang-is-container}}|| o.{{name}} == nil{{/vendorExtensions.x-golang-is-container}}{{/isNullable}} { return nil, false } {{#isNullable}} -{{#isContainer}} +{{#vendorExtensions.x-golang-is-container}} return &o.{{name}}, true -{{/isContainer}} -{{^isContainer}} +{{/vendorExtensions.x-golang-is-container}} +{{^vendorExtensions.x-golang-is-container}} return o.{{name}}.Get(), o.{{name}}.IsSet() -{{/isContainer}} +{{/vendorExtensions.x-golang-is-container}} {{/isNullable}} {{^isNullable}} return &o.{{name}}, true @@ -158,12 +158,12 @@ func (o *{{classname}}) Get{{name}}Ok() (*{{vendorExtensions.x-go-base-type}}, b // Set{{name}} sets field value func (o *{{classname}}) Set{{name}}(v {{vendorExtensions.x-go-base-type}}) { {{#isNullable}} -{{#isContainer}} +{{#vendorExtensions.x-golang-is-container}} o.{{name}} = v -{{/isContainer}} -{{^isContainer}} +{{/vendorExtensions.x-golang-is-container}} +{{^vendorExtensions.x-golang-is-container}} o.{{name}}.Set(&v) -{{/isContainer}} +{{/vendorExtensions.x-golang-is-container}} {{/isNullable}} {{^isNullable}} o.{{name}} = v @@ -174,17 +174,17 @@ func (o *{{classname}}) Set{{name}}(v {{vendorExtensions.x-go-base-type}}) { {{^required}} // Get{{name}} returns the {{name}} field value if set, zero value otherwise{{#isNullable}} (both if not set or set to explicit null){{/isNullable}}. func (o *{{classname}}) Get{{name}}() {{vendorExtensions.x-go-base-type}} { - if o == nil {{^isNullable}}|| o.{{name}} == nil{{/isNullable}}{{#isNullable}}{{^isContainer}}|| o.{{name}}.Get() == nil{{/isContainer}}{{/isNullable}} { + if o == nil {{^isNullable}}|| o.{{name}} == nil{{/isNullable}}{{#isNullable}}{{^vendorExtensions.x-golang-is-container}}|| o.{{name}}.Get() == nil{{/vendorExtensions.x-golang-is-container}}{{/isNullable}} { var ret {{vendorExtensions.x-go-base-type}} return ret } {{#isNullable}} -{{#isContainer}} +{{#vendorExtensions.x-golang-is-container}} return o.{{name}} -{{/isContainer}} -{{^isContainer}} +{{/vendorExtensions.x-golang-is-container}} +{{^vendorExtensions.x-golang-is-container}} return *o.{{name}}.Get() -{{/isContainer}} +{{/vendorExtensions.x-golang-is-container}} {{/isNullable}} {{^isNullable}} return *o.{{name}} @@ -197,16 +197,16 @@ func (o *{{classname}}) Get{{name}}() {{vendorExtensions.x-go-base-type}} { // NOTE: If the value is an explicit nil, `nil, true` will be returned {{/isNullable}} func (o *{{classname}}) Get{{name}}Ok() (*{{vendorExtensions.x-go-base-type}}, bool) { - if o == nil {{^isNullable}}|| o.{{name}} == nil{{/isNullable}}{{#isNullable}}{{#isContainer}}|| o.{{name}} == nil{{/isContainer}}{{/isNullable}} { + if o == nil {{^isNullable}}|| o.{{name}} == nil{{/isNullable}}{{#isNullable}}{{#vendorExtensions.x-golang-is-container}}|| o.{{name}} == nil{{/vendorExtensions.x-golang-is-container}}{{/isNullable}} { return nil, false } {{#isNullable}} -{{#isContainer}} +{{#vendorExtensions.x-golang-is-container}} return &o.{{name}}, true -{{/isContainer}} -{{^isContainer}} +{{/vendorExtensions.x-golang-is-container}} +{{^vendorExtensions.x-golang-is-container}} return o.{{name}}.Get(), o.{{name}}.IsSet() -{{/isContainer}} +{{/vendorExtensions.x-golang-is-container}} {{/isNullable}} {{^isNullable}} return o.{{name}}, true @@ -215,7 +215,7 @@ func (o *{{classname}}) Get{{name}}Ok() (*{{vendorExtensions.x-go-base-type}}, b // Has{{name}} returns a boolean if a field has been set. func (o *{{classname}}) Has{{name}}() bool { - if o != nil && {{^isNullable}}o.{{name}} != nil{{/isNullable}}{{#isNullable}}{{#isContainer}}o.{{name}} != nil{{/isContainer}}{{^isContainer}}o.{{name}}.IsSet(){{/isContainer}}{{/isNullable}} { + if o != nil && {{^isNullable}}o.{{name}} != nil{{/isNullable}}{{#isNullable}}{{#vendorExtensions.x-golang-is-container}}o.{{name}} != nil{{/vendorExtensions.x-golang-is-container}}{{^vendorExtensions.x-golang-is-container}}o.{{name}}.IsSet(){{/vendorExtensions.x-golang-is-container}}{{/isNullable}} { return true } @@ -225,19 +225,19 @@ func (o *{{classname}}) Has{{name}}() bool { // Set{{name}} gets a reference to the given {{dataType}} and assigns it to the {{name}} field. func (o *{{classname}}) Set{{name}}(v {{vendorExtensions.x-go-base-type}}) { {{#isNullable}} -{{#isContainer}} +{{#vendorExtensions.x-golang-is-container}} o.{{name}} = v -{{/isContainer}} -{{^isContainer}} +{{/vendorExtensions.x-golang-is-container}} +{{^vendorExtensions.x-golang-is-container}} o.{{name}}.Set(&v) -{{/isContainer}} +{{/vendorExtensions.x-golang-is-container}} {{/isNullable}} {{^isNullable}} o.{{name}} = &v {{/isNullable}} } {{#isNullable}} -{{^isContainer}} +{{^vendorExtensions.x-golang-is-container}} // Set{{name}}Nil sets the value for {{name}} to be an explicit nil func (o *{{classname}}) Set{{name}}Nil() { o.{{name}}.Set(nil) @@ -247,7 +247,7 @@ func (o *{{classname}}) Set{{name}}Nil() { func (o *{{classname}}) Unset{{name}}() { o.{{name}}.Unset() } -{{/isContainer}} +{{/vendorExtensions.x-golang-is-container}} {{/isNullable}} {{/required}} @@ -269,17 +269,17 @@ func (o {{classname}}) MarshalJSON() ([]byte, error) { {{#vars}} {{! if argument is nullable, only serialize it if it is set}} {{#isNullable}} - {{#isContainer}} + {{#vendorExtensions.x-golang-is-container}} {{! support for container fields is not ideal at this point because of lack of Nullable* types}} if o.{{name}} != nil { toSerialize["{{baseName}}"] = o.{{name}} } - {{/isContainer}} - {{^isContainer}} + {{/vendorExtensions.x-golang-is-container}} + {{^vendorExtensions.x-golang-is-container}} if {{#required}}true{{/required}}{{^required}}o.{{name}}.IsSet(){{/required}} { toSerialize["{{baseName}}"] = o.{{name}}.Get() } - {{/isContainer}} + {{/vendorExtensions.x-golang-is-container}} {{/isNullable}} {{! if argument is not nullable, don't set it if it is nil}} {{^isNullable}} diff --git a/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml b/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml index d9aedbba9c6..74598c6ce70 100644 --- a/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml @@ -1250,6 +1250,23 @@ components: type: integer format: int32 description: User Status + arbitraryObject: + type: object + description: test code generation for objects + Value must be a map of strings to values. It cannot be the 'null' value. + arbitraryNullableObject: + type: object + description: test code generation for nullable objects. + Value must be a map of strings to values or the 'null' value. + nullable: true + arbitraryTypeValue: + description: test code generation for any type + Value can be any type - string, number, boolean, array or object. + arbitraryNullableTypeValue: + description: test code generation for any type + Value can be any type - string, number, boolean, array, object or + the 'null' value. + nullable: true xml: name: User Tag: diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/api/openapi.yaml b/samples/openapi3/client/petstore/go-experimental/go-petstore/api/openapi.yaml index f27d7ff9c2d..e44571cb5f1 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/api/openapi.yaml +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/api/openapi.yaml @@ -1299,9 +1299,13 @@ components: lastName: lastName password: password userStatus: 6 + arbitraryTypeValue: "" + arbitraryNullableTypeValue: "" phone: phone id: 0 + arbitraryObject: '{}' email: email + arbitraryNullableObject: '{}' username: username properties: id: @@ -1324,6 +1328,22 @@ components: description: User Status format: int32 type: integer + arbitraryObject: + description: test code generation for objects Value must be a map of strings + to values. It cannot be the 'null' value. + type: object + arbitraryNullableObject: + description: test code generation for nullable objects. Value must be a + map of strings to values or the 'null' value. + nullable: true + type: object + arbitraryTypeValue: + description: test code generation for any type Value can be any type - string, + number, boolean, array or object. + arbitraryNullableTypeValue: + description: test code generation for any type Value can be any type - string, + number, boolean, array, object or the 'null' value. + nullable: true type: object xml: name: User diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/docs/NullableClass.md b/samples/openapi3/client/petstore/go-experimental/go-petstore/docs/NullableClass.md index edb2d4a01ee..e24e6447515 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/docs/NullableClass.md +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/docs/NullableClass.md @@ -10,12 +10,12 @@ Name | Type | Description | Notes **StringProp** | Pointer to **NullableString** | | [optional] **DateProp** | Pointer to **NullableString** | | [optional] **DatetimeProp** | Pointer to [**NullableTime**](time.Time.md) | | [optional] -**ArrayNullableProp** | Pointer to [**[]map[string]interface{}**](map[string]interface{}.md) | | [optional] -**ArrayAndItemsNullableProp** | Pointer to [**[]map[string]interface{}**](map[string]interface{}.md) | | [optional] -**ArrayItemsNullable** | Pointer to [**[]map[string]interface{}**](map[string]interface{}.md) | | [optional] -**ObjectNullableProp** | Pointer to [**map[string]map[string]interface{}**](map[string]interface{}.md) | | [optional] -**ObjectAndItemsNullableProp** | Pointer to [**map[string]map[string]interface{}**](map[string]interface{}.md) | | [optional] -**ObjectItemsNullable** | Pointer to [**map[string]map[string]interface{}**](map[string]interface{}.md) | | [optional] +**ArrayNullableProp** | Pointer to **[]map[string]interface{}** | | [optional] +**ArrayAndItemsNullableProp** | Pointer to **[]map[string]interface{}** | | [optional] +**ArrayItemsNullable** | Pointer to **[]map[string]interface{}** | | [optional] +**ObjectNullableProp** | Pointer to **map[string]map[string]interface{}** | | [optional] +**ObjectAndItemsNullableProp** | Pointer to **map[string]map[string]interface{}** | | [optional] +**ObjectItemsNullable** | Pointer to **map[string]map[string]interface{}** | | [optional] ## Methods diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/docs/User.md b/samples/openapi3/client/petstore/go-experimental/go-petstore/docs/User.md index a6bea41030b..4a78be2ab84 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/docs/User.md +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/docs/User.md @@ -12,6 +12,10 @@ Name | Type | Description | Notes **Password** | Pointer to **string** | | [optional] **Phone** | Pointer to **string** | | [optional] **UserStatus** | Pointer to **int32** | User Status | [optional] +**ArbitraryObject** | Pointer to [**map[string]interface{}**](.md) | test code generation for objects Value must be a map of strings to values. It cannot be the 'null' value. | [optional] +**ArbitraryNullableObject** | Pointer to [**map[string]interface{}**](.md) | test code generation for nullable objects. Value must be a map of strings to values or the 'null' value. | [optional] +**ArbitraryTypeValue** | Pointer to **interface{}** | test code generation for any type Value can be any type - string, number, boolean, array or object. | [optional] +**ArbitraryNullableTypeValue** | Pointer to **interface{}** | test code generation for any type Value can be any type - string, number, boolean, array, object or the 'null' value. | [optional] ## Methods @@ -232,6 +236,126 @@ SetUserStatus sets UserStatus field to given value. HasUserStatus returns a boolean if a field has been set. +### GetArbitraryObject + +`func (o *User) GetArbitraryObject() map[string]interface{}` + +GetArbitraryObject returns the ArbitraryObject field if non-nil, zero value otherwise. + +### GetArbitraryObjectOk + +`func (o *User) GetArbitraryObjectOk() (*map[string]interface{}, bool)` + +GetArbitraryObjectOk returns a tuple with the ArbitraryObject field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetArbitraryObject + +`func (o *User) SetArbitraryObject(v map[string]interface{})` + +SetArbitraryObject sets ArbitraryObject field to given value. + +### HasArbitraryObject + +`func (o *User) HasArbitraryObject() bool` + +HasArbitraryObject returns a boolean if a field has been set. + +### GetArbitraryNullableObject + +`func (o *User) GetArbitraryNullableObject() map[string]interface{}` + +GetArbitraryNullableObject returns the ArbitraryNullableObject field if non-nil, zero value otherwise. + +### GetArbitraryNullableObjectOk + +`func (o *User) GetArbitraryNullableObjectOk() (*map[string]interface{}, bool)` + +GetArbitraryNullableObjectOk returns a tuple with the ArbitraryNullableObject field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetArbitraryNullableObject + +`func (o *User) SetArbitraryNullableObject(v map[string]interface{})` + +SetArbitraryNullableObject sets ArbitraryNullableObject field to given value. + +### HasArbitraryNullableObject + +`func (o *User) HasArbitraryNullableObject() bool` + +HasArbitraryNullableObject returns a boolean if a field has been set. + +### SetArbitraryNullableObjectNil + +`func (o *User) SetArbitraryNullableObjectNil(b bool)` + + SetArbitraryNullableObjectNil sets the value for ArbitraryNullableObject to be an explicit nil + +### UnsetArbitraryNullableObject +`func (o *User) UnsetArbitraryNullableObject()` + +UnsetArbitraryNullableObject ensures that no value is present for ArbitraryNullableObject, not even an explicit nil +### GetArbitraryTypeValue + +`func (o *User) GetArbitraryTypeValue() interface{}` + +GetArbitraryTypeValue returns the ArbitraryTypeValue field if non-nil, zero value otherwise. + +### GetArbitraryTypeValueOk + +`func (o *User) GetArbitraryTypeValueOk() (*interface{}, bool)` + +GetArbitraryTypeValueOk returns a tuple with the ArbitraryTypeValue field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetArbitraryTypeValue + +`func (o *User) SetArbitraryTypeValue(v interface{})` + +SetArbitraryTypeValue sets ArbitraryTypeValue field to given value. + +### HasArbitraryTypeValue + +`func (o *User) HasArbitraryTypeValue() bool` + +HasArbitraryTypeValue returns a boolean if a field has been set. + +### GetArbitraryNullableTypeValue + +`func (o *User) GetArbitraryNullableTypeValue() interface{}` + +GetArbitraryNullableTypeValue returns the ArbitraryNullableTypeValue field if non-nil, zero value otherwise. + +### GetArbitraryNullableTypeValueOk + +`func (o *User) GetArbitraryNullableTypeValueOk() (*interface{}, bool)` + +GetArbitraryNullableTypeValueOk returns a tuple with the ArbitraryNullableTypeValue field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetArbitraryNullableTypeValue + +`func (o *User) SetArbitraryNullableTypeValue(v interface{})` + +SetArbitraryNullableTypeValue sets ArbitraryNullableTypeValue field to given value. + +### HasArbitraryNullableTypeValue + +`func (o *User) HasArbitraryNullableTypeValue() bool` + +HasArbitraryNullableTypeValue returns a boolean if a field has been set. + +### SetArbitraryNullableTypeValueNil + +`func (o *User) SetArbitraryNullableTypeValueNil(b bool)` + + SetArbitraryNullableTypeValueNil sets the value for ArbitraryNullableTypeValue to be an explicit nil + +### UnsetArbitraryNullableTypeValue +`func (o *User) UnsetArbitraryNullableTypeValue()` + +UnsetArbitraryNullableTypeValue ensures that no value is present for ArbitraryNullableTypeValue, not even an explicit nil [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_user.go b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_user.go index 838cf38d979..9a9bd7dcfda 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_user.go +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_user.go @@ -24,6 +24,14 @@ type User struct { Phone *string `json:"phone,omitempty"` // User Status UserStatus *int32 `json:"userStatus,omitempty"` + // test code generation for objects Value must be a map of strings to values. It cannot be the 'null' value. + ArbitraryObject *map[string]interface{} `json:"arbitraryObject,omitempty"` + // test code generation for nullable objects. Value must be a map of strings to values or the 'null' value. + ArbitraryNullableObject map[string]interface{} `json:"arbitraryNullableObject,omitempty"` + // test code generation for any type Value can be any type - string, number, boolean, array or object. + ArbitraryTypeValue *interface{} `json:"arbitraryTypeValue,omitempty"` + // test code generation for any type Value can be any type - string, number, boolean, array, object or the 'null' value. + ArbitraryNullableTypeValue interface{} `json:"arbitraryNullableTypeValue,omitempty"` } // NewUser instantiates a new User object @@ -299,6 +307,136 @@ func (o *User) SetUserStatus(v int32) { o.UserStatus = &v } +// GetArbitraryObject returns the ArbitraryObject field value if set, zero value otherwise. +func (o *User) GetArbitraryObject() map[string]interface{} { + if o == nil || o.ArbitraryObject == nil { + var ret map[string]interface{} + return ret + } + return *o.ArbitraryObject +} + +// GetArbitraryObjectOk returns a tuple with the ArbitraryObject field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetArbitraryObjectOk() (*map[string]interface{}, bool) { + if o == nil || o.ArbitraryObject == nil { + return nil, false + } + return o.ArbitraryObject, true +} + +// HasArbitraryObject returns a boolean if a field has been set. +func (o *User) HasArbitraryObject() bool { + if o != nil && o.ArbitraryObject != nil { + return true + } + + return false +} + +// SetArbitraryObject gets a reference to the given map[string]interface{} and assigns it to the ArbitraryObject field. +func (o *User) SetArbitraryObject(v map[string]interface{}) { + o.ArbitraryObject = &v +} + +// GetArbitraryNullableObject returns the ArbitraryNullableObject field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *User) GetArbitraryNullableObject() map[string]interface{} { + if o == nil { + var ret map[string]interface{} + return ret + } + return o.ArbitraryNullableObject +} + +// GetArbitraryNullableObjectOk returns a tuple with the ArbitraryNullableObject field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *User) GetArbitraryNullableObjectOk() (*map[string]interface{}, bool) { + if o == nil || o.ArbitraryNullableObject == nil { + return nil, false + } + return &o.ArbitraryNullableObject, true +} + +// HasArbitraryNullableObject returns a boolean if a field has been set. +func (o *User) HasArbitraryNullableObject() bool { + if o != nil && o.ArbitraryNullableObject != nil { + return true + } + + return false +} + +// SetArbitraryNullableObject gets a reference to the given map[string]interface{} and assigns it to the ArbitraryNullableObject field. +func (o *User) SetArbitraryNullableObject(v map[string]interface{}) { + o.ArbitraryNullableObject = v +} + +// GetArbitraryTypeValue returns the ArbitraryTypeValue field value if set, zero value otherwise. +func (o *User) GetArbitraryTypeValue() interface{} { + if o == nil || o.ArbitraryTypeValue == nil { + var ret interface{} + return ret + } + return *o.ArbitraryTypeValue +} + +// GetArbitraryTypeValueOk returns a tuple with the ArbitraryTypeValue field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *User) GetArbitraryTypeValueOk() (*interface{}, bool) { + if o == nil || o.ArbitraryTypeValue == nil { + return nil, false + } + return o.ArbitraryTypeValue, true +} + +// HasArbitraryTypeValue returns a boolean if a field has been set. +func (o *User) HasArbitraryTypeValue() bool { + if o != nil && o.ArbitraryTypeValue != nil { + return true + } + + return false +} + +// SetArbitraryTypeValue gets a reference to the given interface{} and assigns it to the ArbitraryTypeValue field. +func (o *User) SetArbitraryTypeValue(v interface{}) { + o.ArbitraryTypeValue = &v +} + +// GetArbitraryNullableTypeValue returns the ArbitraryNullableTypeValue field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *User) GetArbitraryNullableTypeValue() interface{} { + if o == nil { + var ret interface{} + return ret + } + return o.ArbitraryNullableTypeValue +} + +// GetArbitraryNullableTypeValueOk returns a tuple with the ArbitraryNullableTypeValue field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *User) GetArbitraryNullableTypeValueOk() (*interface{}, bool) { + if o == nil || o.ArbitraryNullableTypeValue == nil { + return nil, false + } + return &o.ArbitraryNullableTypeValue, true +} + +// HasArbitraryNullableTypeValue returns a boolean if a field has been set. +func (o *User) HasArbitraryNullableTypeValue() bool { + if o != nil && o.ArbitraryNullableTypeValue != nil { + return true + } + + return false +} + +// SetArbitraryNullableTypeValue gets a reference to the given interface{} and assigns it to the ArbitraryNullableTypeValue field. +func (o *User) SetArbitraryNullableTypeValue(v interface{}) { + o.ArbitraryNullableTypeValue = v +} + func (o User) MarshalJSON() ([]byte, error) { toSerialize := map[string]interface{}{} if o.Id != nil { @@ -325,6 +463,18 @@ func (o User) MarshalJSON() ([]byte, error) { if o.UserStatus != nil { toSerialize["userStatus"] = o.UserStatus } + if o.ArbitraryObject != nil { + toSerialize["arbitraryObject"] = o.ArbitraryObject + } + if o.ArbitraryNullableObject != nil { + toSerialize["arbitraryNullableObject"] = o.ArbitraryNullableObject + } + if o.ArbitraryTypeValue != nil { + toSerialize["arbitraryTypeValue"] = o.ArbitraryTypeValue + } + if o.ArbitraryNullableTypeValue != nil { + toSerialize["arbitraryNullableTypeValue"] = o.ArbitraryNullableTypeValue + } return json.Marshal(toSerialize) } diff --git a/samples/openapi3/client/petstore/go/go-petstore/docs/NullableClass.md b/samples/openapi3/client/petstore/go/go-petstore/docs/NullableClass.md index 7c70bd76808..a5758169c98 100644 --- a/samples/openapi3/client/petstore/go/go-petstore/docs/NullableClass.md +++ b/samples/openapi3/client/petstore/go/go-petstore/docs/NullableClass.md @@ -10,12 +10,12 @@ Name | Type | Description | Notes **StringProp** | Pointer to **string** | | [optional] **DateProp** | Pointer to **string** | | [optional] **DatetimeProp** | Pointer to [**time.Time**](time.Time.md) | | [optional] -**ArrayNullableProp** | Pointer to [**[]map[string]interface{}**](map[string]interface{}.md) | | [optional] -**ArrayAndItemsNullableProp** | Pointer to [**[]map[string]interface{}**](map[string]interface{}.md) | | [optional] -**ArrayItemsNullable** | [**[]map[string]interface{}**](map[string]interface{}.md) | | [optional] -**ObjectNullableProp** | Pointer to [**map[string]map[string]interface{}**](map[string]interface{}.md) | | [optional] -**ObjectAndItemsNullableProp** | Pointer to [**map[string]map[string]interface{}**](map[string]interface{}.md) | | [optional] -**ObjectItemsNullable** | [**map[string]map[string]interface{}**](map[string]interface{}.md) | | [optional] +**ArrayNullableProp** | Pointer to **[]map[string]interface{}** | | [optional] +**ArrayAndItemsNullableProp** | Pointer to **[]map[string]interface{}** | | [optional] +**ArrayItemsNullable** | **[]map[string]interface{}** | | [optional] +**ObjectNullableProp** | Pointer to **map[string]map[string]interface{}** | | [optional] +**ObjectAndItemsNullableProp** | Pointer to **map[string]map[string]interface{}** | | [optional] +**ObjectItemsNullable** | **map[string]map[string]interface{}** | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/samples/openapi3/client/petstore/python-experimental/docs/User.md b/samples/openapi3/client/petstore/python-experimental/docs/User.md index 52ff07af296..3e15df53f8f 100644 --- a/samples/openapi3/client/petstore/python-experimental/docs/User.md +++ b/samples/openapi3/client/petstore/python-experimental/docs/User.md @@ -11,6 +11,10 @@ Name | Type | Description | Notes **password** | **str** | | [optional] **phone** | **str** | | [optional] **user_status** | **int** | User Status | [optional] +**arbitrary_object** | **bool, date, datetime, dict, float, int, list, str** | test code generation for objects Value must be a map of strings to values. It cannot be the 'null' value. | [optional] +**arbitrary_nullable_object** | **bool, date, datetime, dict, float, int, list, str, none_type** | test code generation for nullable objects. Value must be a map of strings to values or the 'null' value. | [optional] +**arbitrary_type_value** | **object** | test code generation for any type Value can be any type - string, number, boolean, array or object. | [optional] +**arbitrary_nullable_type_value** | **object, none_type** | test code generation for any type Value can be any type - string, number, boolean, array, object or the 'null' value. | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/samples/openapi3/client/petstore/python-experimental/petstore_api/models/user.py b/samples/openapi3/client/petstore/python-experimental/petstore_api/models/user.py index 3b2eeb54b3d..31e9e36b1ad 100644 --- a/samples/openapi3/client/petstore/python-experimental/petstore_api/models/user.py +++ b/samples/openapi3/client/petstore/python-experimental/petstore_api/models/user.py @@ -82,6 +82,10 @@ class User(ModelNormal): 'password': (str,), # noqa: E501 'phone': (str,), # noqa: E501 'user_status': (int,), # noqa: E501 + 'arbitrary_object': (bool, date, datetime, dict, float, int, list, str,), # noqa: E501 + 'arbitrary_nullable_object': (bool, date, datetime, dict, float, int, list, str, none_type,), # noqa: E501 + 'arbitrary_type_value': (object,), # noqa: E501 + 'arbitrary_nullable_type_value': (object, none_type,), # noqa: E501 } @staticmethod @@ -97,6 +101,10 @@ class User(ModelNormal): 'password': 'password', # noqa: E501 'phone': 'phone', # noqa: E501 'user_status': 'userStatus', # noqa: E501 + 'arbitrary_object': 'arbitraryObject', # noqa: E501 + 'arbitrary_nullable_object': 'arbitraryNullableObject', # noqa: E501 + 'arbitrary_type_value': 'arbitraryTypeValue', # noqa: E501 + 'arbitrary_nullable_type_value': 'arbitraryNullableTypeValue', # noqa: E501 } @staticmethod @@ -136,6 +144,10 @@ class User(ModelNormal): password (str): [optional] # noqa: E501 phone (str): [optional] # noqa: E501 user_status (int): User Status. [optional] # noqa: E501 + arbitrary_object (bool, date, datetime, dict, float, int, list, str): test code generation for objects Value must be a map of strings to values. It cannot be the 'null' value.. [optional] # noqa: E501 + arbitrary_nullable_object (bool, date, datetime, dict, float, int, list, str, none_type): test code generation for nullable objects. Value must be a map of strings to values or the 'null' value.. [optional] # noqa: E501 + arbitrary_type_value (object): test code generation for any type Value can be any type - string, number, boolean, array or object.. [optional] # noqa: E501 + arbitrary_nullable_type_value (object, none_type): test code generation for any type Value can be any type - string, number, boolean, array, object or the 'null' value.. [optional] # noqa: E501 """ self._data_store = {}