Better "Any Type" support (#6091)

* better anytype support

* add tests for any type

* fix test with any_value

* fix tests

* fix case additionalProperties: {}

* test with CI

* remove check in map schema

* Revert "remove check in map schema"

This reverts commit e016c4155f1bd8753e894d87bad8e70eee29f3d5.

* fix tests, comment out map schema fix

* fix tests

* fix tests with correct codegen model

* fix tests

* fix tests for map of any type

* fix array of any type

* fix array of any type

* update samples, remove log

* add typemapping to go, python
This commit is contained in:
William Cheng 2020-04-30 21:23:55 +08:00 committed by GitHub
parent cc623ba429
commit 3bbaedd9bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 302 additions and 152 deletions

View File

@ -34,7 +34,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
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, isUri, isEmail, isFreeFormObject;
isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isFreeFormObject, isAnyType;
public boolean isListContainer, isMapContainer;
public boolean isFile;
public boolean isEnum;
@ -178,6 +178,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
output.isUri = this.isUri;
output.isEmail = this.isEmail;
output.isFreeFormObject = this.isFreeFormObject;
output.isAnyType = this.isAnyType;
output.isListContainer = this.isListContainer;
output.isMapContainer = this.isMapContainer;
output.isExplode = this.isExplode;
@ -188,7 +189,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
@Override
public int hashCode() {
return Objects.hash(isFormParam, isQueryParam, isPathParam, isHeaderParam, isCookieParam, isBodyParam, hasMore, isContainer, secondaryParam, isCollectionFormatMulti, isPrimitiveType, isModel, isExplode, baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue, enumName, style, example, jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isFreeFormObject, isListContainer, isMapContainer, isFile, isEnum, _enum, allowableValues, items, mostInnerItems, vendorExtensions, hasValidation, getMaxProperties(), getMinProperties(), isNullable, required, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(), getPattern(), getMaxItems(), getMinItems(), getUniqueItems(), multipleOf);
return Objects.hash(isFormParam, isQueryParam, isPathParam, isHeaderParam, isCookieParam, isBodyParam, hasMore, isContainer, secondaryParam, isCollectionFormatMulti, isPrimitiveType, isModel, isExplode, baseName, paramName, dataType, datatypeWithEnum, dataFormat, collectionFormat, description, unescapedDescription, baseType, defaultValue, enumName, style, example, jsonSchema, isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary, isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isFreeFormObject, isAnyType, isListContainer, isMapContainer, isFile, isEnum, _enum, allowableValues, items, mostInnerItems, vendorExtensions, hasValidation, getMaxProperties(), getMinProperties(), isNullable, required, getMaximum(), getExclusiveMaximum(), getMinimum(), getExclusiveMinimum(), getMaxLength(), getMinLength(), getPattern(), getMaxItems(), getMinItems(), getUniqueItems(), multipleOf);
}
@Override
@ -225,6 +226,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
isUri == that.isUri &&
isEmail == that.isEmail &&
isFreeFormObject == that.isFreeFormObject &&
isAnyType == that.isAnyType &&
isListContainer == that.isListContainer &&
isMapContainer == that.isMapContainer &&
isFile == that.isFile &&
@ -312,6 +314,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
sb.append(", isUri=").append(isUri);
sb.append(", isEmail=").append(isEmail);
sb.append(", isFreeFormObject=").append(isFreeFormObject);
sb.append(", isAnyType=").append(isAnyType);
sb.append(", isListContainer=").append(isListContainer);
sb.append(", isMapContainer=").append(isMapContainer);
sb.append(", isFile=").append(isFile);

View File

@ -49,6 +49,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
public boolean isEmail;
public boolean isModel;
public boolean isFreeFormObject;
public boolean isAnyType;
public boolean isDefault;
public boolean simpleType;
public boolean primitiveType;
@ -77,7 +78,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
public int hashCode() {
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, isModel, isFreeFormObject, isDefault, simpleType, primitiveType,
isDateTime, isUuid, isEmail, isModel, isFreeFormObject, isAnyType, isDefault, simpleType, primitiveType,
isMapContainer, isListContainer, isBinary, isFile, schema, jsonSchema, vendorExtensions,
getMaxProperties(), getMinProperties(), uniqueItems, getMaxItems(), getMinItems(), getMaxLength(),
getMinLength(), exclusiveMinimum, exclusiveMaximum, getMinimum(), getMaximum(), getPattern());
@ -105,6 +106,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
isEmail == that.isEmail &&
isModel == that.isModel &&
isFreeFormObject == that.isFreeFormObject &&
isAnyType == that.isAnyType &&
isDefault == that.isDefault &&
simpleType == that.simpleType &&
primitiveType == that.primitiveType &&
@ -295,6 +297,7 @@ public class CodegenResponse implements IJsonSchemaValidationProperties {
sb.append(", isEmail=").append(isEmail);
sb.append(", isModel=").append(isModel);
sb.append(", isFreeFormObject=").append(isFreeFormObject);
sb.append(", isAnyType=").append(isAnyType);
sb.append(", isDefault=").append(isDefault);
sb.append(", simpleType=").append(simpleType);
sb.append(", primitiveType=").append(primitiveType);

View File

@ -1398,6 +1398,7 @@ public class DefaultCodegen implements CodegenConfig {
typeMapping.put("UUID", "UUID");
typeMapping.put("URI", "URI");
typeMapping.put("BigDecimal", "BigDecimal");
typeMapping.put("AnyType", "oas_any_type_not_mapped");
instantiationTypes = new HashMap<String, String>();
@ -1863,9 +1864,9 @@ public class DefaultCodegen implements CodegenConfig {
/**
* Return the name of the oneOf schema.
*
* <p>
* This name is used to set the value of CodegenProperty.openApiType.
*
* <p>
* If the 'x-one-of-name' extension is specified in the OAS document, return that value.
* Otherwise, a name is constructed by creating a comma-separated list of all the names
* of the oneOf schemas.
@ -1981,6 +1982,8 @@ public class DefaultCodegen implements CodegenConfig {
return "object";
} else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) { // having property implies it's a model
return "object";
} else if (ModelUtils.isAnyTypeSchema(schema)) {
return "AnyType";
} else if (StringUtils.isNotEmpty(schema.getType())) {
LOGGER.warn("Unknown type found in the schema: " + schema.getType());
return schema.getType();
@ -2427,6 +2430,7 @@ public class DefaultCodegen implements CodegenConfig {
* Recursively look in Schema sc for the discriminator discPropName
* and return a CodegenProperty with the dataType and required params set
* the returned CodegenProperty may not be required and it may not be of type string
*
* @param composedSchemaName The name of the sc Schema
* @param sc The Schema that may contain the discriminator
* @param discPropName The String that is the discriminator propertyName in the schema
@ -2503,6 +2507,7 @@ public class DefaultCodegen implements CodegenConfig {
* Recursively look in Schema sc for the discriminator and return it
* Schema sc location
* OpenAPI openAPI the spec where we are searching for the discriminator
*
* @param sc The Schema that may contain the discriminator
*/
private Discriminator recursiveGetDiscriminator(Schema sc, OpenAPI openAPI) {
@ -2573,6 +2578,7 @@ public class DefaultCodegen implements CodegenConfig {
* the required discriminator. If they don't contain the required
* discriminator or the discriminator is the wrong type then an error is
* thrown
*
* @param composedSchemaName The String model name of the composed schema where we are setting the discriminator map
* @param discPropName The String that is the discriminator propertyName in the schema
* @param c The ComposedSchema that contains the discriminator and oneOf/anyOf schemas
@ -2635,7 +2641,7 @@ public class DefaultCodegen implements CodegenConfig {
}
protected List<MappedModel> getAllOfDescendants(String thisSchemaName, OpenAPI openAPI) {
ArrayList<String> queue = new ArrayList();;
ArrayList<String> queue = new ArrayList();
List<MappedModel> descendentSchemas = new ArrayList();
Map<String, Schema> schemas = ModelUtils.getSchemas(openAPI);
String currentSchemaName = thisSchemaName;
@ -2968,6 +2974,8 @@ public class DefaultCodegen implements CodegenConfig {
} else if (ModelUtils.isFreeFormObject(p)) {
property.isFreeFormObject = true;
} else if (ModelUtils.isAnyTypeSchema(p)) {
property.isAnyType = true;
} else if (ModelUtils.isArraySchema(p)) {
// default to string if inner item is undefined
ArraySchema arraySchema = (ArraySchema) p;
@ -3074,18 +3082,13 @@ public class DefaultCodegen implements CodegenConfig {
} else if (ModelUtils.isFreeFormObject(p)) {
property.isFreeFormObject = true;
property.baseType = getSchemaType(p);
} else if (ModelUtils.isAnyTypeSchema(p)) {
property.isAnyType = true;
property.baseType = getSchemaType(p);
} else { // model
// TODO revise the logic below
//if (StringUtils.isNotBlank(p.get$ref())) {
// property.baseType = getSimpleRef(p.get$ref());
//}
// --END of revision
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);
@ -3773,6 +3776,8 @@ public class DefaultCodegen implements CodegenConfig {
r.isDateTime = true;
} else if (Boolean.TRUE.equals(cp.isFreeFormObject)) {
r.isFreeFormObject = true;
} else if (Boolean.TRUE.equals(cp.isAnyType)) {
r.isAnyType = true;
} else {
LOGGER.debug("Property type is not primitive: " + cp.dataType);
}
@ -4074,91 +4079,6 @@ public class DefaultCodegen implements CodegenConfig {
} else {
LOGGER.error("ERROR! Not handling " + parameter + " as Body Parameter at the moment");
/* TODO need to revise the logic below to handle body parameter
if (!(parameter instanceof BodyParameter)) {
LOGGER.error("Cannot use Parameter " + parameter + " as Body Parameter");
}
BodyParameter bp = (BodyParameter) param;
Model model = bp.getSchema();
if (model instanceof ModelImpl) {
ModelImpl impl = (ModelImpl) model;
CodegenModel cm = fromModel(bp.getName(), impl);
if (!cm.emptyVars) {
codegen.dataType = getTypeDeclaration(cm.classname);
imports.add(p.dataType);
} else {
Property prop = PropertyBuilder.build(impl.getType(), impl.getFormat(), null);
prop.setRequired(bp.getRequired());
CodegenProperty cp = fromProperty("property", prop);
if (cp != null) {
p.baseType = cp.baseType;
p.dataType = cp.datatype;
p.isPrimitiveType = cp.isPrimitiveType;
p.isBinary = isDataTypeBinary(cp.datatype);
p.isFile = isDataTypeFile(cp.datatype);
if (cp.complexType != null) {
imports.add(cp.complexType);
}
}
// set boolean flag (e.g. isString)
setParameterBooleanFlagWithCodegenProperty(p, cp);
}
} else if (model instanceof ArrayModel) {
// to use the built-in model parsing, we unwrap the ArrayModel
// and get a single property from it
ArrayModel impl = (ArrayModel) model;
// get the single property
ArrayProperty ap = new ArrayProperty().items(impl.getItems());
ap.setRequired(param.getRequired());
CodegenProperty cp = fromProperty("inner", ap);
if (cp.complexType != null) {
imports.add(cp.complexType);
}
imports.add(cp.baseType);
// recursively add import
CodegenProperty innerCp = cp;
while(innerCp != null) {
if(innerCp.complexType != null) {
imports.add(innerCp.complexType);
}
innerCp = innerCp.items;
}
p.items = cp;
p.dataType = cp.datatype;
p.baseType = cp.complexType;
p.isPrimitiveType = cp.isPrimitiveType;
p.isContainer = true;
p.isListContainer = true;
// set boolean flag (e.g. isString)
setParameterBooleanFlagWithCodegenProperty(p, cp);
} else {
Model sub = bp.getSchema();
if (sub instanceof RefModel) {
String name = ((RefModel) sub).getSimpleRef();
name = getAlias(name);
if (typeMapping.containsKey(name)) {
name = typeMapping.get(name);
p.baseType = name;
} else {
name = toModelName(name);
p.baseType = name;
if (defaultIncludes.contains(name)) {
imports.add(name);
}
imports.add(name);
name = getTypeDeclaration(name);
}
p.dataType = name;
}
}
p.paramName = toParamName(bp.getName());
*/
}
if (parameter instanceof QueryParameter || "query".equalsIgnoreCase(parameter.getIn())) {
@ -5128,6 +5048,8 @@ public class DefaultCodegen implements CodegenConfig {
parameter.isPrimitiveType = true;
} else if (Boolean.TRUE.equals(property.isFreeFormObject)) {
parameter.isFreeFormObject = true;
} else if (Boolean.TRUE.equals(property.isAnyType)) {
parameter.isAnyType = true;
} else {
LOGGER.debug("Property type is not primitive: " + property.dataType);
}
@ -5702,7 +5624,7 @@ public class DefaultCodegen implements CodegenConfig {
codegenParameter.dataType = getTypeDeclaration(codegenModelName);
codegenParameter.description = codegenProperty.getDescription();
} else {
if (ModelUtils.getAdditionalProperties(schema) != null) {// http body is map
if (ModelUtils.isMapSchema(schema)) {// http body is map
LOGGER.error("Map should be supported. Please report to openapi-generator github repo about the issue.");
} else if (codegenProperty != null) {
String codegenModelName, codegenModelDescription;

View File

@ -130,6 +130,7 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
// See issue #5387 for more details.
typeMapping.put("object", "map[string]interface{}");
typeMapping.put("interface{}", "interface{}");
typeMapping.put("AnyType", "interface{}");
numberTypes = new HashSet<String>(
Arrays.asList(

View File

@ -134,6 +134,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("date", "date");
typeMapping.put("DateTime", "datetime");
typeMapping.put("object", "object");
typeMapping.put("AnyType", "object");
typeMapping.put("file", "file");
// TODO binary should be mapped to byte array
// mapped to String as a workaround

View File

@ -682,6 +682,12 @@ public class ModelUtils {
once(LOGGER).error("Schema cannot be null in isAnyTypeSchema check");
return false;
}
if (isFreeFormObject(schema)) {
// make sure it's not free form object
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 &&
@ -754,6 +760,11 @@ public class ModelUtils {
if (objSchema.getProperties() == null || objSchema.getProperties().isEmpty()) {
return true;
}
} else if (addlProps instanceof Schema) {
// additionalProperties defined as {}
if (addlProps.getType() == null && (addlProps.getProperties() == null || addlProps.getProperties().isEmpty())) {
return true;
}
}
}
}
@ -1269,12 +1280,10 @@ public class ModelUtils {
Schema s = allSchemas.get(parentName);
if (s != null) {
return hasOrInheritsDiscriminator(s, allSchemas);
}
else {
} else {
LOGGER.error("Failed to obtain schema from {}", parentName);
}
}
else if (schema instanceof ComposedSchema) {
} else if (schema instanceof ComposedSchema) {
final ComposedSchema composed = (ComposedSchema) schema;
final List<Schema> interfaces = getInterfaces(composed);
for (Schema i : interfaces) {

View File

@ -505,7 +505,7 @@ public class JavaClientCodegenTest {
codegen.setOpenAPI(openAPI);
CodegenModel cm1 = codegen.fromModel("MapTest1", test1);
Assert.assertEquals(cm1.getDataType(), "Map");
Assert.assertEquals(cm1.getParent(), "HashMap<String, Object>");
Assert.assertEquals(cm1.getParent(), "HashMap<String, oas_any_type_not_mapped>");
Assert.assertEquals(cm1.getClassname(), "MapTest1");
Schema test2 = openAPI.getComponents().getSchemas().get("MapTest2");
@ -631,4 +631,147 @@ public class JavaClientCodegenTest {
assertEquals("_int", codegen.toApiVarName("int"));
assertEquals("pony", codegen.toApiVarName("pony"));
}
@Test
public void testAnyType() {
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/any_type.yaml");
JavaClientCodegen codegen = new JavaClientCodegen();
Schema test1 = openAPI.getComponents().getSchemas().get("AnyValueModel");
codegen.setOpenAPI(openAPI);
CodegenModel cm1 = codegen.fromModel("AnyValueModel", test1);
Assert.assertEquals(cm1.getClassname(), "AnyValueModel");
final CodegenProperty property1 = cm1.allVars.get(0);
Assert.assertEquals(property1.baseName, "any_value");
Assert.assertEquals(property1.dataType, "oas_any_type_not_mapped");
Assert.assertTrue(property1.hasMore);
Assert.assertFalse(property1.isPrimitiveType);
Assert.assertFalse(property1.isContainer);
Assert.assertFalse(property1.isFreeFormObject);
Assert.assertTrue(property1.isAnyType);
final CodegenProperty property2 = cm1.allVars.get(1);
Assert.assertEquals(property2.baseName, "any_value_with_desc");
Assert.assertEquals(property2.dataType, "oas_any_type_not_mapped");
Assert.assertTrue(property2.hasMore);
Assert.assertFalse(property2.required);
Assert.assertFalse(property2.isPrimitiveType);
Assert.assertFalse(property2.isContainer);
Assert.assertFalse(property2.isFreeFormObject);
Assert.assertTrue(property2.isAnyType);
final CodegenProperty property3 = cm1.allVars.get(2);
Assert.assertEquals(property3.baseName, "any_value_nullable");
Assert.assertEquals(property3.dataType, "oas_any_type_not_mapped");
Assert.assertFalse(property3.hasMore);
Assert.assertFalse(property3.required);
Assert.assertFalse(property3.isPrimitiveType);
Assert.assertFalse(property3.isContainer);
Assert.assertFalse(property3.isFreeFormObject);
Assert.assertTrue(property3.isAnyType);
Schema test2 = openAPI.getComponents().getSchemas().get("AnyValueModelInline");
codegen.setOpenAPI(openAPI);
CodegenModel cm2 = codegen.fromModel("AnyValueModelInline", test2);
Assert.assertEquals(cm2.getClassname(), "AnyValueModelInline");
final CodegenProperty cp1 = cm2.vars.get(0);
Assert.assertEquals(cp1.baseName, "any_value");
Assert.assertEquals(cp1.dataType, "oas_any_type_not_mapped");
Assert.assertTrue(cp1.hasMore);
Assert.assertFalse(cp1.required);
Assert.assertFalse(cp1.isPrimitiveType);
Assert.assertFalse(cp1.isContainer);
Assert.assertFalse(cp1.isFreeFormObject);
Assert.assertTrue(cp1.isAnyType);
final CodegenProperty cp2 = cm2.vars.get(1);
Assert.assertEquals(cp2.baseName, "any_value_with_desc");
Assert.assertEquals(cp2.dataType, "oas_any_type_not_mapped");
Assert.assertTrue(cp2.hasMore);
Assert.assertFalse(cp2.required);
Assert.assertFalse(cp2.isPrimitiveType);
Assert.assertFalse(cp2.isContainer);
Assert.assertFalse(cp2.isFreeFormObject);
Assert.assertTrue(cp2.isAnyType);
final CodegenProperty cp3 = cm2.vars.get(2);
Assert.assertEquals(cp3.baseName, "any_value_nullable");
Assert.assertEquals(cp3.dataType, "oas_any_type_not_mapped");
Assert.assertTrue(cp3.hasMore);
Assert.assertFalse(cp3.required);
Assert.assertFalse(cp3.isPrimitiveType);
Assert.assertFalse(cp3.isContainer);
Assert.assertFalse(cp3.isFreeFormObject);
Assert.assertTrue(cp3.isAnyType);
// map
final CodegenProperty cp4 = cm2.vars.get(3);
Assert.assertEquals(cp4.baseName, "map_any_value");
Assert.assertEquals(cp4.dataType, "Map<String, oas_any_type_not_mapped>");
Assert.assertTrue(cp4.hasMore);
Assert.assertFalse(cp4.required);
Assert.assertFalse(cp4.isPrimitiveType);
Assert.assertTrue(cp4.isContainer);
Assert.assertTrue(cp4.isMapContainer);
Assert.assertTrue(cp4.isFreeFormObject);
Assert.assertFalse(cp4.isAnyType);
final CodegenProperty cp5 = cm2.vars.get(4);
Assert.assertEquals(cp5.baseName, "map_any_value_with_desc");
Assert.assertEquals(cp5.dataType, "Map<String, oas_any_type_not_mapped>");
Assert.assertTrue(cp5.hasMore);
Assert.assertFalse(cp5.required);
Assert.assertFalse(cp5.isPrimitiveType);
Assert.assertTrue(cp5.isContainer);
Assert.assertTrue(cp5.isMapContainer);
Assert.assertTrue(cp5.isFreeFormObject);
Assert.assertFalse(cp5.isAnyType);
final CodegenProperty cp6 = cm2.vars.get(5);
Assert.assertEquals(cp6.baseName, "map_any_value_nullable");
Assert.assertEquals(cp6.dataType, "Map<String, oas_any_type_not_mapped>");
Assert.assertTrue(cp6.hasMore);
Assert.assertFalse(cp6.required);
Assert.assertFalse(cp6.isPrimitiveType);
Assert.assertTrue(cp6.isContainer);
Assert.assertTrue(cp6.isMapContainer);
Assert.assertTrue(cp6.isFreeFormObject);
Assert.assertFalse(cp6.isAnyType);
// array
final CodegenProperty cp7 = cm2.vars.get(6);
Assert.assertEquals(cp7.baseName, "array_any_value");
Assert.assertEquals(cp7.dataType, "List<oas_any_type_not_mapped>");
Assert.assertTrue(cp7.hasMore);
Assert.assertFalse(cp7.required);
Assert.assertFalse(cp7.isPrimitiveType);
Assert.assertTrue(cp7.isContainer);
Assert.assertTrue(cp7.isListContainer);
Assert.assertFalse(cp7.isFreeFormObject);
Assert.assertFalse(cp7.isAnyType);
final CodegenProperty cp8 = cm2.vars.get(7);
Assert.assertEquals(cp8.baseName, "array_any_value_with_desc");
Assert.assertEquals(cp8.dataType, "List<oas_any_type_not_mapped>");
Assert.assertTrue(cp8.hasMore);
Assert.assertFalse(cp8.required);
Assert.assertFalse(cp8.isPrimitiveType);
Assert.assertTrue(cp8.isContainer);
Assert.assertTrue(cp8.isListContainer);
Assert.assertFalse(cp8.isFreeFormObject);
Assert.assertFalse(cp8.isAnyType);
final CodegenProperty cp9 = cm2.vars.get(8);
Assert.assertEquals(cp9.baseName, "array_any_value_nullable");
Assert.assertEquals(cp9.dataType, "List<oas_any_type_not_mapped>");
Assert.assertFalse(cp9.hasMore);
Assert.assertFalse(cp9.required);
Assert.assertFalse(cp9.isPrimitiveType);
Assert.assertTrue(cp9.isContainer);
Assert.assertTrue(cp9.isListContainer);
Assert.assertFalse(cp9.isFreeFormObject);
Assert.assertFalse(cp9.isAnyType);
}
}

View File

@ -0,0 +1,59 @@
openapi: 3.0.1
info:
title: ping test
version: '1.0'
servers:
- url: 'http://localhost:8000/'
paths:
/ping:
get:
operationId: pingGet
responses:
'201':
description: OK
components:
schemas:
AnyValue: {}
AnyValueWithDesc:
description: Can be any value - string, number, boolean, array or object.
AnyValueNullable:
nullable: true
description: Can be any value, including `null`.
AnyValueModel:
description: test any value
type: object
properties:
any_value:
$ref: '#/components/schemas/AnyValue'
any_value_with_desc:
$ref: '#/components/schemas/AnyValueWithDesc'
any_value_nullable:
$ref: '#/components/schemas/AnyValueNullable'
AnyValueModelInline:
description: test any value inline
type: object
properties:
any_value: {}
any_value_with_desc:
description: inline any value
any_value_nullable:
nullable: true
description: inline any value nullable
map_any_value:
additionalProperties: {}
map_any_value_with_desc:
additionalProperties:
description: inline any value
map_any_value_nullable:
additionalProperties:
nullable: true
description: inline any value nullable
array_any_value:
items: {}
array_any_value_with_desc:
items:
description: inline any value
array_any_value_nullable:
items:
nullable: true
description: inline any value nullable

View File

@ -34,4 +34,13 @@ components:
type: object
description: This type example 4
additionalProperties: false
MapObject:
properties:
map_test1:
$ref: '#/components/schemas/MapTest1'
map_test2:
$ref: '#/components/schemas/MapTest2'
map_test3:
$ref: '#/components/schemas/MapTest3'
other_obj:
$ref: '#/components/schemas/OtherObj'

View File

@ -14,8 +14,8 @@ Name | Type | Description | Notes
**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 &#39;null&#39; 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 &#39;null&#39; 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 &#39;null&#39; value. | [optional]
**ArbitraryTypeValue** | Pointer to [**interface{}**](.md) | test code generation for any type Value can be any type - string, number, boolean, array or object. | [optional]
**ArbitraryNullableTypeValue** | Pointer to [**interface{}**](.md) | test code generation for any type Value can be any type - string, number, boolean, array, object or the &#39;null&#39; value. | [optional]
## Methods