diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenParameter.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenParameter.java
index 62aa1f22b8bbded2acb4d611a3d32318fa083e06..7624815b9489e64062f5141d22332026e1ae9f92 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenParameter.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenParameter.java
@@ -27,11 +27,12 @@ public class CodegenParameter {
             isCookieParam, isBodyParam, hasMore, isContainer,
             secondaryParam, isCollectionFormatMulti, isPrimitiveType, isModel;
     public String baseName, paramName, dataType, datatypeWithEnum, dataFormat,
-          collectionFormat, description, unescapedDescription, baseType, defaultValue, enumName;
+            collectionFormat, description, unescapedDescription, baseType, defaultValue, enumName;
 
     public String example; // example value (x-example)
     public String jsonSchema;
-    public boolean isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isEmail;
+    public boolean isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary,
+            isBoolean, isDate, isDateTime, isUuid, isEmail, isFreeFormObject;
     public boolean isListContainer, isMapContainer;
     public boolean isFile;
     public boolean isEnum;
@@ -94,7 +95,7 @@ public class CodegenParameter {
      * See http://json-schema.org/latest/json-schema-validation.html#anchor14
      */
     public Number multipleOf;
-    
+
     public CodegenParameter copy() {
         CodegenParameter output = new CodegenParameter();
         output.isFile = this.isFile;
@@ -148,7 +149,7 @@ public class CodegenParameter {
         if (this.mostInnerItems != null) {
             output.mostInnerItems = this.mostInnerItems;
         }
-        if(this.vendorExtensions != null){
+        if (this.vendorExtensions != null) {
             output.vendorExtensions = new HashMap<String, Object>(this.vendorExtensions);
         }
         output.hasValidation = this.hasValidation;
@@ -167,6 +168,7 @@ public class CodegenParameter {
         output.isDateTime = this.isDateTime;
         output.isUuid = this.isUuid;
         output.isEmail = this.isEmail;
+        output.isFreeFormObject = this.isFreeFormObject;
         output.isListContainer = this.isListContainer;
         output.isMapContainer = this.isMapContainer;
 
@@ -259,6 +261,8 @@ public class CodegenParameter {
             return false;
         if (isEmail != that.isEmail)
             return false;
+        if (isFreeFormObject != that.isFreeFormObject)
+            return false;
         if (isListContainer != that.isListContainer)
             return false;
         if (isMapContainer != that.isMapContainer)
@@ -307,18 +311,18 @@ public class CodegenParameter {
 
     @Override
     public int hashCode() {
-        int result = isFormParam ? 13:31;
-        result = 31 * result + (isQueryParam ? 13:31);
-        result = 31 * result + (isPathParam ? 13:31);
-        result = 31 * result + (isHeaderParam ? 13:31);
-        result = 31 * result + (isCookieParam ? 13:31);
-        result = 31 * result + (isBodyParam ? 13:31);
-        result = 31 * result + (hasMore ? 13:31);
-        result = 31 * result + (isContainer ? 13:31);
-        result = 31 * result + (secondaryParam ? 13:31);
-        result = 31 * result + (isCollectionFormatMulti ? 13:31);
-        result = 31 * result + (isPrimitiveType ? 13:31);
-        result = 31 * result + (isModel ? 13:31);
+        int result = isFormParam ? 13 : 31;
+        result = 31 * result + (isQueryParam ? 13 : 31);
+        result = 31 * result + (isPathParam ? 13 : 31);
+        result = 31 * result + (isHeaderParam ? 13 : 31);
+        result = 31 * result + (isCookieParam ? 13 : 31);
+        result = 31 * result + (isBodyParam ? 13 : 31);
+        result = 31 * result + (hasMore ? 13 : 31);
+        result = 31 * result + (isContainer ? 13 : 31);
+        result = 31 * result + (secondaryParam ? 13 : 31);
+        result = 31 * result + (isCollectionFormatMulti ? 13 : 31);
+        result = 31 * result + (isPrimitiveType ? 13 : 31);
+        result = 31 * result + (isModel ? 13 : 31);
         result = 31 * result + (baseName != null ? baseName.hashCode() : 0);
         result = 31 * result + (paramName != null ? paramName.hashCode() : 0);
         result = 31 * result + (dataType != null ? dataType.hashCode() : 0);
@@ -332,42 +336,43 @@ public class CodegenParameter {
         result = 31 * result + (defaultValue != null ? defaultValue.hashCode() : 0);
         result = 31 * result + (example != null ? example.hashCode() : 0);
         result = 31 * result + (jsonSchema != null ? jsonSchema.hashCode() : 0);
-        result = 31 * result + (isString ? 13:31);
-        result = 31 * result + (isNumeric ? 13:31);
-        result = 31 * result + (isInteger ? 13:31);
-        result = 31 * result + (isLong ? 13:31);
-        result = 31 * result + (isFloat ? 13:31);
-        result = 31 * result + (isNumber ? 13:31);
-        result = 31 * result + (isDouble ? 13:31);
-        result = 31 * result + (isByteArray ? 13:31);
-        result = 31 * result + (isBinary ? 13:31);
-        result = 31 * result + (isBoolean ? 13:31);
-        result = 31 * result + (isDate ? 13:31);
-        result = 31 * result + (isDateTime ? 13:31);
-        result = 31 * result + (isUuid ? 13:31);
-        result = 31 * result + (isEmail ? 13:31);
-        result = 31 * result + (isListContainer ? 13:31);
-        result = 31 * result + (isMapContainer ? 13:31);
-        result = 31 * result + (isFile ? 13:31);
+        result = 31 * result + (isString ? 13 : 31);
+        result = 31 * result + (isNumeric ? 13 : 31);
+        result = 31 * result + (isInteger ? 13 : 31);
+        result = 31 * result + (isLong ? 13 : 31);
+        result = 31 * result + (isFloat ? 13 : 31);
+        result = 31 * result + (isNumber ? 13 : 31);
+        result = 31 * result + (isDouble ? 13 : 31);
+        result = 31 * result + (isByteArray ? 13 : 31);
+        result = 31 * result + (isBinary ? 13 : 31);
+        result = 31 * result + (isBoolean ? 13 : 31);
+        result = 31 * result + (isDate ? 13 : 31);
+        result = 31 * result + (isDateTime ? 13 : 31);
+        result = 31 * result + (isUuid ? 13 : 31);
+        result = 31 * result + (isEmail ? 13 : 31);
+        result = 31 * result + (isFreeFormObject ? 13 : 31);
+        result = 31 * result + (isListContainer ? 13 : 31);
+        result = 31 * result + (isMapContainer ? 13 : 31);
+        result = 31 * result + (isFile ? 13 : 31);
         result = 31 * result + (isEnum ? 1 : 0);
         result = 31 * result + (_enum != null ? _enum.hashCode() : 0);
         result = 31 * result + (allowableValues != null ? allowableValues.hashCode() : 0);
         result = 31 * result + (items != null ? items.hashCode() : 0);
         result = 31 * result + (mostInnerItems != null ? mostInnerItems.hashCode() : 0);
         result = 31 * result + (vendorExtensions != null ? vendorExtensions.hashCode() : 0);
-        result = 31 * result + (hasValidation ? 13:31);
-        result = 31 * result + (isNullable ? 13:31);
-        result = 31 * result + (required ? 13:31);
+        result = 31 * result + (hasValidation ? 13 : 31);
+        result = 31 * result + (isNullable ? 13 : 31);
+        result = 31 * result + (required ? 13 : 31);
         result = 31 * result + (maximum != null ? maximum.hashCode() : 0);
-        result = 31 * result + (exclusiveMaximum ? 13:31);
+        result = 31 * result + (exclusiveMaximum ? 13 : 31);
         result = 31 * result + (minimum != null ? minimum.hashCode() : 0);
-        result = 31 * result + (exclusiveMinimum ? 13:31);
+        result = 31 * result + (exclusiveMinimum ? 13 : 31);
         result = 31 * result + (maxLength != null ? maxLength.hashCode() : 0);
         result = 31 * result + (minLength != null ? minLength.hashCode() : 0);
         result = 31 * result + (pattern != null ? pattern.hashCode() : 0);
         result = 31 * result + (maxItems != null ? maxItems.hashCode() : 0);
         result = 31 * result + (minItems != null ? minItems.hashCode() : 0);
-        result = 31 * result + (uniqueItems ? 13:31);
+        result = 31 * result + (uniqueItems ? 13 : 31);
         result = 31 * result + (multipleOf != null ? multipleOf.hashCode() : 0);
         return result;
     }
@@ -414,6 +419,7 @@ public class CodegenParameter {
                 ", isDateTime=" + isDateTime +
                 ", isUuid=" + isUuid +
                 ", isEmail=" + isEmail +
+                ", isFreeFormObject=" + isFreeFormObject +
                 ", isListContainer=" + isListContainer +
                 ", isMapContainer=" + isMapContainer +
                 ", isFile=" + isFile +
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 3fa796d45f280928c3b5a2d2c72afd90b3b82f8f..7f6688c134ed10ec67ebde5f02698fa065c8a443 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
@@ -25,10 +25,12 @@ import java.util.Objects;
 
 public class CodegenProperty implements Cloneable {
     public String baseName, complexType, getter, setter, description, dataType,
-          datatypeWithEnum, dataFormat, name, min, max, defaultValue, defaultValueWithParam,
-          baseType, containerType, title;
+            datatypeWithEnum, dataFormat, name, min, max, defaultValue, defaultValueWithParam,
+            baseType, containerType, title;
 
-    /** The 'description' string without escape charcters needed by some programming languages/targets */
+    /**
+     * The 'description' string without escape charcters needed by some programming languages/targets
+     */
     public String unescapedDescription;
 
     /**
@@ -56,7 +58,8 @@ public class CodegenProperty implements Cloneable {
     public boolean hasMore, required, secondaryParam;
     public boolean hasMoreNonReadOnly; // for model constructor, true if next property is not readonly
     public boolean isPrimitiveType, isModel, isContainer, isNotContainer;
-    public boolean isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary, isFile, isBoolean, isDate, isDateTime, isUuid, isEmail;
+    public boolean isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary, isFile,
+            isBoolean, isDate, isDateTime, isUuid, isEmail, isFreeFormObject;
     public boolean isListContainer, isMapContainer;
     public boolean isEnum;
     public boolean isReadOnly;
@@ -84,7 +87,7 @@ public class CodegenProperty implements Cloneable {
     public String xmlNamespace;
     public boolean isXmlWrapped = false;
 
-        public String getBaseName() {
+    public String getBaseName() {
         return baseName;
     }
 
@@ -125,9 +128,9 @@ public class CodegenProperty implements Cloneable {
     }
 
     /**
+     * @return dataType
      * @deprecated since version 3.0.0, use {@link #getDataType()} instead.<br>
      * May be removed with the next major release (4.0)
-     * @return dataType
      */
     @Deprecated
     public String getDatatype() {
@@ -411,8 +414,7 @@ public class CodegenProperty implements Cloneable {
     }
 
     @Override
-    public int hashCode()
-    {
+    public int hashCode() {
         final int prime = 31;
         int result = 1;
         result = prime * result + ((_enum == null) ? 0 : _enum.hashCode());
@@ -429,19 +431,19 @@ public class CodegenProperty implements Cloneable {
         result = prime * result + ((description == null) ? 0 : description.hashCode());
         result = prime * result + ((title == null) ? 0 : title.hashCode());
         result = prime * result + ((example == null) ? 0 : example.hashCode());
-        result = prime * result + (exclusiveMaximum ? 13:31);
-        result = prime * result + (exclusiveMinimum ? 13:31);
+        result = prime * result + (exclusiveMaximum ? 13 : 31);
+        result = prime * result + (exclusiveMinimum ? 13 : 31);
         result = prime * result + ((getter == null) ? 0 : getter.hashCode());
-        result = prime * result + (hasMore  ? 13:31);
-        result = prime * result + ((hasMoreNonReadOnly  ? 13:31));
-        result = prime * result + ((isContainer  ? 13:31));
+        result = prime * result + (hasMore ? 13 : 31);
+        result = prime * result + ((hasMoreNonReadOnly ? 13 : 31));
+        result = prime * result + ((isContainer ? 13 : 31));
         result = prime * result + (isEnum ? 1231 : 1237);
-        result = prime * result + ((isNotContainer ? 13:31));
-        result = prime * result + ((isPrimitiveType  ? 13:31));
-        result = prime * result + ((isModel  ? 13:31));
-        result = prime * result + ((isReadOnly  ? 13:31));
-        result = prime * result + ((isWriteOnly  ? 13:31));
-        result = prime * result + ((isNullable  ? 13:31));
+        result = prime * result + ((isNotContainer ? 13 : 31));
+        result = prime * result + ((isPrimitiveType ? 13 : 31));
+        result = prime * result + ((isModel ? 13 : 31));
+        result = prime * result + ((isReadOnly ? 13 : 31));
+        result = prime * result + ((isWriteOnly ? 13 : 31));
+        result = prime * result + ((isNullable ? 13 : 31));
         result = prime * result + ((items == null) ? 0 : items.hashCode());
         result = prime * result + ((mostInnerItems == null) ? 0 : mostInnerItems.hashCode());
         result = prime * result + ((jsonSchema == null) ? 0 : jsonSchema.hashCode());
@@ -453,29 +455,30 @@ public class CodegenProperty implements Cloneable {
         result = prime * result + ((minimum == null) ? 0 : minimum.hashCode());
         result = prime * result + ((name == null) ? 0 : name.hashCode());
         result = prime * result + ((pattern == null) ? 0 : pattern.hashCode());
-        result = prime * result + ((required  ? 13:31));
-        result = prime * result + ((secondaryParam ? 13:31));
+        result = prime * result + ((required ? 13 : 31));
+        result = prime * result + ((secondaryParam ? 13 : 31));
         result = prime * result + ((setter == null) ? 0 : setter.hashCode());
         result = prime * result + ((unescapedDescription == null) ? 0 : unescapedDescription.hashCode());
         result = prime * result + ((vendorExtensions == null) ? 0 : vendorExtensions.hashCode());
-        result = prime * result + ((hasValidation  ? 13:31));
-        result = prime * result + ((isString  ? 13:31));
-        result = prime * result + ((isNumeric ? 13:31));
-        result = prime * result + ((isInteger ? 13:31));
-        result = prime * result + ((isLong  ?13:31));
-        result = prime * result + ((isNumber ? 13:31));
-        result = prime * result + ((isFloat ? 13:31));
-        result = prime * result + ((isDouble  ? 13:31));
-        result = prime * result + ((isByteArray  ? 13:31));
-        result = prime * result + ((isBinary  ? 13:31));
-        result = prime * result + ((isFile  ? 13:31));
-        result = prime * result + ((isBoolean  ? 13:31));
-        result = prime * result + ((isDate  ? 13:31));
-        result = prime * result + ((isDateTime ? 13:31));
-        result = prime * result + ((isUuid ? 13:31));
-        result = prime * result + ((isEmail ? 13:31));
-        result = prime * result + ((isMapContainer ? 13:31));
-        result = prime * result + ((isListContainer  ? 13:31));
+        result = prime * result + ((hasValidation ? 13 : 31));
+        result = prime * result + ((isString ? 13 : 31));
+        result = prime * result + ((isNumeric ? 13 : 31));
+        result = prime * result + ((isInteger ? 13 : 31));
+        result = prime * result + ((isLong ? 13 : 31));
+        result = prime * result + ((isNumber ? 13 : 31));
+        result = prime * result + ((isFloat ? 13 : 31));
+        result = prime * result + ((isDouble ? 13 : 31));
+        result = prime * result + ((isByteArray ? 13 : 31));
+        result = prime * result + ((isBinary ? 13 : 31));
+        result = prime * result + ((isFile ? 13 : 31));
+        result = prime * result + ((isBoolean ? 13 : 31));
+        result = prime * result + ((isDate ? 13 : 31));
+        result = prime * result + ((isDateTime ? 13 : 31));
+        result = prime * result + ((isUuid ? 13 : 31));
+        result = prime * result + ((isEmail ? 13 : 31));
+        result = prime * result + ((isFreeFormObject ? 13 : 31));
+        result = prime * result + ((isMapContainer ? 13 : 31));
+        result = prime * result + ((isListContainer ? 13 : 31));
         result = prime * result + Objects.hashCode(isInherited);
         result = prime * result + Objects.hashCode(discriminatorValue);
         result = prime * result + Objects.hashCode(nameInCamelCase);
@@ -483,11 +486,11 @@ public class CodegenProperty implements Cloneable {
         result = prime * result + Objects.hashCode(enumName);
         result = prime * result + ((maxItems == null) ? 0 : maxItems.hashCode());
         result = prime * result + ((minItems == null) ? 0 : minItems.hashCode());
-        result = prime * result + ((isXmlAttribute  ? 13:31));
+        result = prime * result + ((isXmlAttribute ? 13 : 31));
         result = prime * result + ((xmlPrefix == null) ? 0 : xmlPrefix.hashCode());
         result = prime * result + ((xmlName == null) ? 0 : xmlName.hashCode());
         result = prime * result + ((xmlNamespace == null) ? 0 : xmlNamespace.hashCode());
-        result = prime * result + ((isXmlWrapped  ? 13:31));
+        result = prime * result + ((isXmlWrapped ? 13 : 31));
         return result;
     }
 
@@ -657,6 +660,9 @@ public class CodegenProperty implements Cloneable {
         if (this.isEmail != other.isEmail) {
             return false;
         }
+        if (this.isFreeFormObject != other.isFreeFormObject) {
+            return false;
+        }
         if (this.isBinary != other.isBinary) {
             return false;
         }
@@ -724,7 +730,7 @@ public class CodegenProperty implements Cloneable {
             if (this.mostInnerItems != null) {
                 cp.mostInnerItems = this.mostInnerItems;
             }
-            if(this.vendorExtensions != null){
+            if (this.vendorExtensions != null) {
                 cp.vendorExtensions = new HashMap<String, Object>(this.vendorExtensions);
             }
             return cp;
@@ -785,11 +791,12 @@ public class CodegenProperty implements Cloneable {
                 ", isDateTime=" + isDateTime +
                 ", isUuid=" + isUuid +
                 ", isEmail=" + isEmail +
+                ", isFreeFormObject=" + isFreeFormObject +
                 ", isListContainer=" + isListContainer +
                 ", isMapContainer=" + isMapContainer +
                 ", isEnum=" + isEnum +
                 ", isReadOnly=" + isReadOnly +
-                ", isWriteOnly=" + isWriteOnly+
+                ", isWriteOnly=" + isWriteOnly +
                 ", isNullable=" + isNullable +
                 ", _enum=" + _enum +
                 ", allowableValues=" + allowableValues +
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenResponse.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenResponse.java
index 642e44a810f6da8ec76abdb4d7dd2eb129ed95c7..e4241ee00eb9257697b2401c16a43da60a02e6a5 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenResponse.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenResponse.java
@@ -17,11 +17,7 @@
 
 package org.openapitools.codegen;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
 
 public class CodegenResponse {
     public final List<CodegenProperty> headers = new ArrayList<CodegenProperty>();
@@ -30,7 +26,8 @@ public class CodegenResponse {
     public List<Map<String, Object>> examples;
     public String dataType, baseType, containerType;
     public boolean hasHeaders;
-    public boolean isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBoolean, isDate, isDateTime, isUuid, isEmail;
+    public boolean isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBoolean, isDate,
+            isDateTime, isUuid, isEmail, isModel, isFreeFormObject;
     public boolean isDefault;
     public boolean simpleType;
     public boolean primitiveType;
@@ -48,76 +45,90 @@ public class CodegenResponse {
 
     @Override
     public String toString() {
-        return String.format(Locale.ROOT, "%s(%s)", code, containerType);
+        return "CodegenResponse{" +
+                "headers=" + headers +
+                ", code='" + code + '\'' +
+                ", message='" + message + '\'' +
+                ", hasMore=" + hasMore +
+                ", examples=" + examples +
+                ", dataType='" + dataType + '\'' +
+                ", baseType='" + baseType + '\'' +
+                ", containerType='" + containerType + '\'' +
+                ", hasHeaders=" + hasHeaders +
+                ", isString=" + isString +
+                ", isNumeric=" + isNumeric +
+                ", isInteger=" + isInteger +
+                ", isLong=" + isLong +
+                ", isNumber=" + isNumber +
+                ", isFloat=" + isFloat +
+                ", isDouble=" + isDouble +
+                ", isByteArray=" + isByteArray +
+                ", isBoolean=" + isBoolean +
+                ", isDate=" + isDate +
+                ", isDateTime=" + isDateTime +
+                ", isUuid=" + isUuid +
+                ", isEmail=" + isEmail +
+                ", isFreeFormObject=" + isFreeFormObject +
+                ", isModel=" + isModel +
+                ", isDefault=" + isDefault +
+                ", simpleType=" + simpleType +
+                ", primitiveType=" + primitiveType +
+                ", isMapContainer=" + isMapContainer +
+                ", isListContainer=" + isListContainer +
+                ", isBinary=" + isBinary +
+                ", isFile=" + isFile +
+                ", schema=" + schema +
+                ", jsonSchema='" + jsonSchema + '\'' +
+                ", vendorExtensions=" + vendorExtensions +
+                '}';
     }
 
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-
         CodegenResponse that = (CodegenResponse) o;
-
-        if (!headers.equals(that.headers))
-            return false;
-        if (code != null ? !code.equals(that.code) : that.code != null)
-            return false;
-        if (message != null ? !message.equals(that.message) : that.message != null)
-            return false;
-        if (hasMore != that.hasMore)
-            return false;
-        if (examples != null ? !examples.equals(that.examples) : that.examples != null)
-            return false;
-        if (dataType != null ? !dataType.equals(that.dataType) : that.dataType != null)
-            return false;
-        if (baseType != null ? !baseType.equals(that.baseType) : that.baseType != null)
-            return false;
-        if (containerType != null ? !containerType.equals(that.containerType) : that.containerType != null)
-            return false;
-        if (isDefault != that.isDefault)
-            return false;
-        if (simpleType != that.simpleType)
-            return false;
-        if (primitiveType != that.primitiveType)
-            return false;
-        if (isMapContainer != that.isMapContainer)
-            return false;
-        if (isListContainer != that.isListContainer)
-            return false;
-        if (isBinary != that.isBinary)
-            return false;
-        if (isFile != that.isFile)
-            return false;
-        if (isNumeric != that.isNumeric)
-            return false;
-        if (schema != null ? !schema.equals(that.schema) : that.schema != null)
-            return false;
-        if (vendorExtensions != null ? !vendorExtensions.equals(that.vendorExtensions) : that.vendorExtensions != null)
-            return false;
-        return jsonSchema != null ? jsonSchema.equals(that.jsonSchema) : that.jsonSchema == null;
+        return hasMore == that.hasMore &&
+                hasHeaders == that.hasHeaders &&
+                isString == that.isString &&
+                isNumeric == that.isNumeric &&
+                isInteger == that.isInteger &&
+                isLong == that.isLong &&
+                isNumber == that.isNumber &&
+                isFloat == that.isFloat &&
+                isDouble == that.isDouble &&
+                isByteArray == that.isByteArray &&
+                isBoolean == that.isBoolean &&
+                isDate == that.isDate &&
+                isDateTime == that.isDateTime &&
+                isUuid == that.isUuid &&
+                isEmail == that.isEmail &&
+                isFreeFormObject == that.isFreeFormObject &&
+                isModel == that.isModel &&
+                isDefault == that.isDefault &&
+                simpleType == that.simpleType &&
+                primitiveType == that.primitiveType &&
+                isMapContainer == that.isMapContainer &&
+                isListContainer == that.isListContainer &&
+                isBinary == that.isBinary &&
+                isFile == that.isFile &&
+                Objects.equals(headers, that.headers) &&
+                Objects.equals(code, that.code) &&
+                Objects.equals(message, that.message) &&
+                Objects.equals(examples, that.examples) &&
+                Objects.equals(dataType, that.dataType) &&
+                Objects.equals(baseType, that.baseType) &&
+                Objects.equals(containerType, that.containerType) &&
+                Objects.equals(schema, that.schema) &&
+                Objects.equals(jsonSchema, that.jsonSchema) &&
+                Objects.equals(vendorExtensions, that.vendorExtensions);
     }
 
     @Override
     public int hashCode() {
-        int result = headers.hashCode();
-        result = 31 * result + (code != null ? code.hashCode() : 0);
-        result = 31 * result + (message != null ? message.hashCode() : 0);
-        result = 31 * result + (hasMore ? 13:31);
-        result = 31 * result + (examples != null ? examples.hashCode() : 0);
-        result = 31 * result + (dataType != null ? dataType.hashCode() : 0);
-        result = 31 * result + (baseType != null ? baseType.hashCode() : 0);
-        result = 31 * result + (containerType != null ? containerType.hashCode() : 0);
-        result = 31 * result + (isDefault ? 13:31);
-        result = 31 * result + (isNumeric ? 13:31);
-        result = 31 * result + (simpleType ? 13:31);
-        result = 31 * result + (primitiveType ? 13:31);
-        result = 31 * result + (isMapContainer ? 13:31);
-        result = 31 * result + (isListContainer ? 13:31);
-        result = 31 * result + (isBinary ? 13:31);
-        result = 31 * result + (isFile ? 13:31);
-        result = 31 * result + (schema != null ? schema.hashCode() : 0);
-        result = 31 * result + (jsonSchema != null ? jsonSchema.hashCode() : 0);
-        result = 31 * result + (vendorExtensions != null ? vendorExtensions.hashCode() : 0);
-        return result;
+        return Objects.hash(headers, code, message, hasMore, examples, dataType, baseType, containerType, hasHeaders,
+                isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBoolean, isDate,
+                isDateTime, isUuid, isEmail, isFreeFormObject, isModel, isDefault, simpleType, primitiveType, isMapContainer,
+                isListContainer, isBinary, isFile, schema, jsonSchema, vendorExtensions);
     }
 }
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 dd47986cec1abb66a1cf43afa71bb7c0825b9366..e8a4cc5f9bb4bbd2f036ca24897f88e5df1e594f 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
@@ -1152,6 +1152,8 @@ public class DefaultCodegen implements CodegenConfig {
             codegenParameter.example = "38400000-8cf0-11bd-b23e-10b96e4ef00d";
         } else if (Boolean.TRUE.equals(codegenParameter.isString)) {
             codegenParameter.example = codegenParameter.paramName + "_example";
+        } else if (Boolean.TRUE.equals(codegenParameter.isFreeFormObject)) {
+            codegenParameter.example = "Object";
         }
 
     }
@@ -1375,6 +1377,8 @@ public class DefaultCodegen implements CodegenConfig {
             return "UUID";
         } else if (ModelUtils.isStringSchema(schema)) {
             return "string";
+        } else if (ModelUtils.isFreeFormObject(schema)) {
+            return "object";
         } else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) { // having property implies it's a model
             return "object";
         } else if (StringUtils.isNotEmpty(schema.getType())) {
@@ -1685,7 +1689,8 @@ public class DefaultCodegen implements CodegenConfig {
         return m;
     }
 
-    private CodegenDiscriminator createDiscriminator(String schemaName, Schema schema, Map<String, Schema> allDefinitions) {
+    private CodegenDiscriminator createDiscriminator(String schemaName, Schema
+            schema, Map<String, Schema> allDefinitions) {
         if (schema.getDiscriminator() == null) {
             return null;
         }
@@ -1717,7 +1722,8 @@ public class DefaultCodegen implements CodegenConfig {
         addParentContainer(codegenModel, codegenModel.name, schema);
     }
 
-    protected void addProperties(Map<String, Schema> properties, List<String> required, Schema schema, Map<String, Schema> allSchemas) {
+    protected void addProperties(Map<String, Schema> properties, List<String> required, Schema
+            schema, Map<String, Schema> allSchemas) {
         if (schema instanceof ComposedSchema) {
             ComposedSchema composedSchema = (ComposedSchema) schema;
             if (composedSchema.getAllOf() == null) {
@@ -2010,6 +2016,9 @@ public class DefaultCodegen implements CodegenConfig {
             // handle inner property
             CodegenProperty cp = fromProperty("inner", ModelUtils.getAdditionalProperties(p));
             updatePropertyForMap(property, cp);
+        } else if (ModelUtils.isFreeFormObject(p)) {
+            property.isFreeFormObject = true;
+            property.baseType = getSchemaType(p);
         } else { // model
             // TODO revise the logic below
             //if (StringUtils.isNotBlank(p.get$ref())) {
@@ -2212,7 +2221,8 @@ public class DefaultCodegen implements CodegenConfig {
      * @param schemas    a map of OAS models
      * @return Codegen Operation object
      */
-    public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Schema> schemas) {
+    public CodegenOperation fromOperation(String path, String httpMethod, Operation
+            operation, Map<String, Schema> schemas) {
         return fromOperation(path, httpMethod, operation, schemas, null);
     }
 
@@ -2576,6 +2586,7 @@ public class DefaultCodegen implements CodegenConfig {
             } else {
                 if (cp.complexType != null) {
                     r.baseType = cp.complexType;
+                    r.isModel = true;
                 } else {
                     r.baseType = cp.baseType;
                 }
@@ -2616,6 +2627,8 @@ public class DefaultCodegen implements CodegenConfig {
                 r.isDate = true;
             } else if (Boolean.TRUE.equals(cp.isDateTime)) {
                 r.isDateTime = true;
+            } else if (Boolean.TRUE.equals(cp.isFreeFormObject)) {
+                r.isFreeFormObject = true;
             } else {
                 LOGGER.debug("Property type is not primitive: " + cp.dataType);
             }
@@ -2651,7 +2664,8 @@ public class DefaultCodegen implements CodegenConfig {
      * @param openAPI  a OAS object representing the spec
      * @return Codegen Response object
      */
-    public CodegenCallback fromCallback(String name, Callback callback, Map<String, Schema> schemas, OpenAPI openAPI) {
+    public CodegenCallback fromCallback(String name, Callback callback, Map<String, Schema> schemas, OpenAPI
+            openAPI) {
         CodegenCallback c = new CodegenCallback();
         c.name = name;
 
@@ -3227,7 +3241,8 @@ public class DefaultCodegen implements CodegenConfig {
      * @param operations   map of Codegen operations
      */
     @SuppressWarnings("static-method")
-    public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
+    public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation
+            co, Map<String, List<CodegenOperation>> operations) {
         List<CodegenOperation> opList = operations.get(tag);
         if (opList == null) {
             opList = new ArrayList<CodegenOperation>();
@@ -3334,7 +3349,8 @@ public class DefaultCodegen implements CodegenConfig {
      * @param properties model properties (schemas)
      * @return model properties with direct reference to schemas
      */
-    private Map<String, Schema> unaliasPropertySchema(Map<String, Schema> allSchemas, Map<String, Schema> properties) {
+    private Map<String, Schema> unaliasPropertySchema
+    (Map<String, Schema> allSchemas, Map<String, Schema> properties) {
         if (properties != null) {
             for (String key : properties.keySet()) {
                 properties.put(key, ModelUtils.unaliasSchema(allSchemas, properties.get(key)));
@@ -3375,7 +3391,8 @@ public class DefaultCodegen implements CodegenConfig {
         }
     }
 
-    private void addVars(CodegenModel m, List<CodegenProperty> vars, Map<String, Schema> properties, Set<String> mandatory) {
+    private void addVars(CodegenModel
+                                 m, List<CodegenProperty> vars, Map<String, Schema> properties, Set<String> mandatory) {
         // convert set to list so that we can access the next entry in the loop
         List<Map.Entry<String, Schema>> propertyList = new ArrayList<Map.Entry<String, Schema>>(properties.entrySet());
         final int totalCount = propertyList.size();
@@ -3888,6 +3905,8 @@ public class DefaultCodegen implements CodegenConfig {
         } else if (Boolean.TRUE.equals(property.isDateTime)) {
             parameter.isDateTime = true;
             parameter.isPrimitiveType = true;
+        } else if (Boolean.TRUE.equals(property.isFreeFormObject)) {
+            parameter.isFreeFormObject = true;
         } else {
             LOGGER.debug("Property type is not primitive: " + property.dataType);
         }
@@ -3961,7 +3980,8 @@ public class DefaultCodegen implements CodegenConfig {
         }
     }
 
-    private void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions) {
+    private void updateEnumVarsWithExtensions
+            (List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions) {
         if (vendorExtensions != null && vendorExtensions.containsKey("x-enum-varnames")) {
             List<String> alias = (List<String>) vendorExtensions.get("x-enum-varnames");
             int size = Math.min(enumVars.size(), alias.size());
@@ -4272,7 +4292,8 @@ public class DefaultCodegen implements CodegenConfig {
         return null;
     }
 
-    public List<CodegenParameter> fromRequestBodyToFormParameters(RequestBody body, Map<String, Schema> schemas, Set<String> imports) {
+    public List<CodegenParameter> fromRequestBodyToFormParameters(RequestBody
+                                                                          body, Map<String, Schema> schemas, Set<String> imports) {
         List<CodegenParameter> parameters = new ArrayList<CodegenParameter>();
         LOGGER.debug("debugging fromRequestBodyToFormParameters= " + body);
         Schema schema = ModelUtils.getSchemaFromRequestBody(body);
@@ -4428,7 +4449,8 @@ public class DefaultCodegen implements CodegenConfig {
         return codegenParameter;
     }
 
-    public CodegenParameter fromRequestBody(RequestBody body, Map<String, Schema> schemas, Set<String> imports, String bodyParameterName) {
+    public CodegenParameter fromRequestBody(RequestBody
+                                                    body, Map<String, Schema> schemas, Set<String> imports, String bodyParameterName) {
         if (body == null) {
             LOGGER.error("body in fromRequestBody cannot be null!");
         }
@@ -4735,7 +4757,7 @@ public class DefaultCodegen implements CodegenConfig {
     /**
      * Set the boolean value indicating the state of the option for post-processing file using envirionment variables.
      *
-     * @param enablePostProcessFile     true to enable post-processing file
+     * @param enablePostProcessFile true to enable post-processing file
      */
     public void setEnablePostProcessFile(boolean enablePostProcessFile) {
         this.enablePostProcessFile = enablePostProcessFile;
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java
index 230100673c7c88f21dd9d4e1407ddbd79c9c6fce..aa5bccbab4ae62bfaf5e8ed587701cf3e23de76c 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ElixirClientCodegen.java
@@ -169,7 +169,7 @@ public class ElixirClientCodegen extends DefaultCodegen implements CodegenConfig
         typeMapping.put("map", "Map");
         typeMapping.put("array", "List");
         typeMapping.put("list", "List");
-        // typeMapping.put("object", "Map");
+        typeMapping.put("object", "Map");
         typeMapping.put("binary", "String");
         typeMapping.put("ByteArray", "String");
         typeMapping.put("UUID", "String");
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 4a1dd19ee6020ac843da720ecdb8370959d4123f..6f495304fcc2acd6f33f727d4a13fcfa8ab0f264 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
@@ -302,9 +302,13 @@ public class ModelUtils {
         if (schema instanceof ObjectSchema) {
             return true;
         }
+
+        // must not be a map
         if (SchemaTypeUtil.OBJECT_TYPE.equals(schema.getType()) && !(schema instanceof MapSchema)) {
             return true;
         }
+
+        // must have at least one property
         if (schema.getType() == null && schema.getProperties() != null && !schema.getProperties().isEmpty()) {
             return true;
         }
@@ -501,7 +505,70 @@ public class ModelUtils {
     }
 
     /**
-     * If a Schema contains a reference to an other Schema with '$ref', returns the referenced Schema if it is found or the actual Schema in the other cases.
+     * Check to see if the schema is a model with at least one properties
+     *
+     * @param schema potentially containing a '$ref'
+     * @return true if it's a model with at least one properties
+     */
+    public static boolean isModel(Schema schema) {
+        if (schema == null) {
+            LOGGER.error("Schema cannot be null in isModel check");
+            return false;
+        }
+
+        // has at least one property
+        if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
+            return true;
+        }
+
+        // composed schema is a model
+        if (schema instanceof ComposedSchema) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Check to see if the schema is a free form object
+     *
+     * @param schema potentially containing a '$ref'
+     * @return true if it's a free-form object
+     */
+    public static boolean isFreeFormObject(Schema schema) {
+        if (schema == null) {
+            LOGGER.error("Schema cannot be null in isFreeFormObject check");
+            return false;
+        }
+
+        // has at least one property
+        if ("object".equals(schema.getType())) {
+            // no properties
+            if ((schema.getProperties() == null || schema.getProperties().isEmpty())) {
+                if (schema.getAdditionalProperties() == null) {
+                    return true;
+                } else {
+                    // additionalProperties set to true
+                    if (schema.getAdditionalProperties() instanceof Boolean
+                            && (Boolean) schema.getAdditionalProperties()) {
+                        return true;
+                    }
+
+                    // additionalProperties is set to {}
+                    if (schema.getAdditionalProperties() instanceof Schema && schema.getAdditionalProperties() != null
+                            && schema.getAdditionalProperties() instanceof ObjectSchema
+                            && ((Schema) schema.getAdditionalProperties()).getProperties().isEmpty()) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * If a Schema contains a reference to another Schema with '$ref', returns the referenced Schema if it is found or the actual Schema in the other cases.
      *
      * @param openAPI specification being checked
      * @param schema  potentially containing a '$ref'
@@ -623,7 +690,7 @@ public class ModelUtils {
     /**
      * If a Callback contains a reference to an other Callback with '$ref', returns the referenced Callback if it is found or the actual Callback in the other cases.
      *
-     * @param openAPI   specification being checked
+     * @param openAPI  specification being checked
      * @param callback potentially containing a '$ref'
      * @return callback without '$ref'
      */
@@ -642,7 +709,7 @@ public class ModelUtils {
         if (name == null) {
             return null;
         }
-        
+
         if (openAPI != null && openAPI.getComponents() != null && openAPI.getComponents().getCallbacks() != null) {
             return openAPI.getComponents().getCallbacks().get(name);
         }
@@ -689,7 +756,8 @@ public class ModelUtils {
      */
     public static Schema unaliasSchema(Map<String, Schema> allSchemas, Schema schema) {
         if (allSchemas == null || allSchemas.isEmpty()) {
-            LOGGER.warn("allSchemas cann't be null/empty in unaliasSchema. Returned 'schema'");
+            // skip the warning as the spec can have no model defined
+            //LOGGER.warn("allSchemas cannot be null/empty in unaliasSchema. Returned 'schema'");
             return schema;
         }
 
@@ -701,6 +769,8 @@ public class ModelUtils {
             } else if (ref.getEnum() != null && !ref.getEnum().isEmpty()) {
                 // top-level enum class
                 return schema;
+            } else if (isFreeFormObject(ref)) {
+                return schema;
             } else if (isArraySchema(ref) || isComposedSchema(ref)) { // array def should be created as models
                 return schema;
             } else if (isMapSchema(ref)) {
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java
index 312a2fa32e3ebde7b3bc6da9fce09e087c97411d..4c6894c17d48b40d42537f92cda586e30f4bc4ee 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java
@@ -238,7 +238,7 @@ public class KotlinClientCodegenModelTest {
         Assert.assertEquals(property1.name, "child");
         Assert.assertEquals(property1.baseType, "Child");
         Assert.assertFalse(property1.required);
-        Assert.assertTrue(property1.isNotContainer);
+        Assert.assertFalse(property1.isContainer);
     }
 
     @DataProvider(name = "modelNames")