mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-07-04 14:40:53 +00:00
Fix nullable models embedded in allOf (#11804)
It is possible, though contrived, for a property to have both isAnyType and isModel set. In this case, when the outer type is nullable, the Go template expects a Nullable* type to be provided by the generator, but it is skipped over instead. This change aligns the generator with the template's expectations.
This commit is contained in:
parent
22a1906480
commit
6f37409d2b
@ -917,6 +917,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
|
|||||||
sb.append(", isArray=").append(isArray);
|
sb.append(", isArray=").append(isArray);
|
||||||
sb.append(", isMap=").append(isMap);
|
sb.append(", isMap=").append(isMap);
|
||||||
sb.append(", isEnum=").append(isEnum);
|
sb.append(", isEnum=").append(isEnum);
|
||||||
|
sb.append(", isAnyType=").append(isAnyType);
|
||||||
sb.append(", isReadOnly=").append(isReadOnly);
|
sb.append(", isReadOnly=").append(isReadOnly);
|
||||||
sb.append(", isWriteOnly=").append(isWriteOnly);
|
sb.append(", isWriteOnly=").append(isWriteOnly);
|
||||||
sb.append(", isNullable=").append(isNullable);
|
sb.append(", isNullable=").append(isNullable);
|
||||||
@ -995,6 +996,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
|
|||||||
isArray == that.isArray &&
|
isArray == that.isArray &&
|
||||||
isMap == that.isMap &&
|
isMap == that.isMap &&
|
||||||
isEnum == that.isEnum &&
|
isEnum == that.isEnum &&
|
||||||
|
isAnyType == that.isAnyType &&
|
||||||
isReadOnly == that.isReadOnly &&
|
isReadOnly == that.isReadOnly &&
|
||||||
isWriteOnly == that.isWriteOnly &&
|
isWriteOnly == that.isWriteOnly &&
|
||||||
isNullable == that.isNullable &&
|
isNullable == that.isNullable &&
|
||||||
@ -1068,9 +1070,9 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
|
|||||||
hasMoreNonReadOnly, isPrimitiveType, isModel, isContainer, isString, isNumeric,
|
hasMoreNonReadOnly, isPrimitiveType, isModel, isContainer, isString, isNumeric,
|
||||||
isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBinary, isFile,
|
isInteger, isLong, isNumber, isFloat, isDouble, isDecimal, isByteArray, isBinary, isFile,
|
||||||
isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isFreeFormObject,
|
isBoolean, isDate, isDateTime, isUuid, isUri, isEmail, isFreeFormObject,
|
||||||
isArray, isMap, isEnum, isReadOnly, isWriteOnly, isNullable, isShort, isUnboundedInteger,
|
isArray, isMap, isEnum, isAnyType, isReadOnly, isWriteOnly, isNullable, isShort,
|
||||||
isSelfReference, isCircularReference, isDiscriminator, _enum, allowableValues,
|
isUnboundedInteger, isSelfReference, isCircularReference, isDiscriminator, _enum,
|
||||||
items, mostInnerItems, additionalProperties, vars, requiredVars,
|
allowableValues, items, mostInnerItems, additionalProperties, vars, requiredVars,
|
||||||
vendorExtensions, hasValidation, isInherited, discriminatorValue, nameInCamelCase,
|
vendorExtensions, hasValidation, isInherited, discriminatorValue, nameInCamelCase,
|
||||||
nameInSnakeCase, enumName, maxItems, minItems, isXmlAttribute, xmlPrefix, xmlName,
|
nameInSnakeCase, enumName, maxItems, minItems, isXmlAttribute, xmlPrefix, xmlName,
|
||||||
xmlNamespace, isXmlWrapped, isNull, additionalPropertiesIsAnyType, hasVars, hasRequired,
|
xmlNamespace, isXmlWrapped, isNull, additionalPropertiesIsAnyType, hasVars, hasRequired,
|
||||||
|
@ -601,7 +601,8 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
|
|||||||
// For primitive types and custom types (e.g. interface{}, map[string]interface{}...),
|
// 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.
|
// 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.
|
// For containers (e.g. Array, Map), the generated code returns the type directly.
|
||||||
if (property.isContainer || property.isFreeFormObject || property.isAnyType) {
|
if (property.isContainer || property.isFreeFormObject
|
||||||
|
|| (property.isAnyType && !property.isModel)) {
|
||||||
property.vendorExtensions.put("x-golang-is-container", true);
|
property.vendorExtensions.put("x-golang-is-container", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -403,8 +403,8 @@ public class GoClientCodegen extends AbstractGoCodegen {
|
|||||||
|
|
||||||
for (CodegenProperty param : Iterables.concat(model.vars, model.allVars, model.requiredVars, model.optionalVars)) {
|
for (CodegenProperty param : Iterables.concat(model.vars, model.allVars, model.requiredVars, model.optionalVars)) {
|
||||||
param.vendorExtensions.put("x-go-base-type", param.dataType);
|
param.vendorExtensions.put("x-go-base-type", param.dataType);
|
||||||
if (!param.isNullable || param.isMap || param.isArray ||
|
if (!param.isNullable || param.isContainer || param.isFreeFormObject
|
||||||
param.isFreeFormObject || param.isAnyType) {
|
|| (param.isAnyType && !param.isModel)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (param.isDateTime) {
|
if (param.isDateTime) {
|
||||||
|
@ -141,4 +141,21 @@ public class GoClientCodegenTest {
|
|||||||
TestUtils.assertFileNotContains(modelFile, "int32 *int32");
|
TestUtils.assertFileNotContains(modelFile, "int32 *int32");
|
||||||
TestUtils.assertFileNotContains(modelFile, "dst.int32");
|
TestUtils.assertFileNotContains(modelFile, "dst.int32");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNullableComposition() throws IOException {
|
||||||
|
File output = Files.createTempDirectory("test").toFile();
|
||||||
|
output.deleteOnExit();
|
||||||
|
|
||||||
|
final CodegenConfigurator configurator = new CodegenConfigurator()
|
||||||
|
.setGeneratorName("go")
|
||||||
|
.setInputSpec("src/test/resources/3_0/allOf_nullable.yaml")
|
||||||
|
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
|
||||||
|
|
||||||
|
DefaultGenerator generator = new DefaultGenerator();
|
||||||
|
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
|
||||||
|
files.forEach(File::deleteOnExit);
|
||||||
|
|
||||||
|
TestUtils.assertFileContains(Paths.get(output + "/model_example.go"), "Child NullableChild");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
openapi: 3.0.1
|
||||||
|
info:
|
||||||
|
version: 1.0.0
|
||||||
|
title: Example
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
servers:
|
||||||
|
- url: http://api.example.xyz/v1
|
||||||
|
paths:
|
||||||
|
/example:
|
||||||
|
get:
|
||||||
|
operationId: list
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Example"
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Child:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
Example:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
child:
|
||||||
|
nullable: true
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/Child'
|
@ -539,10 +539,10 @@ public interface PathHandlerInterface {
|
|||||||
* <p><b>Response headers</b>: [CodegenProperty{openApiType='integer', baseName='X-Rate-Limit', complexType='null', getter='getxRateLimit', setter='setxRateLimit', description='calls per hour allowed by the user', dataType='Integer', datatypeWithEnum='Integer', dataFormat='int32', name='xRateLimit', min='null', max='null', defaultValue='null', defaultValueWithParam=' = data.X-Rate-Limit;', baseType='Integer', containerType='null', title='null', unescapedDescription='calls per hour allowed by the user', maxLength=null, minLength=null, pattern='null', example='null', jsonSchema='{
|
* <p><b>Response headers</b>: [CodegenProperty{openApiType='integer', baseName='X-Rate-Limit', complexType='null', getter='getxRateLimit', setter='setxRateLimit', description='calls per hour allowed by the user', dataType='Integer', datatypeWithEnum='Integer', dataFormat='int32', name='xRateLimit', min='null', max='null', defaultValue='null', defaultValueWithParam=' = data.X-Rate-Limit;', baseType='Integer', containerType='null', title='null', unescapedDescription='calls per hour allowed by the user', maxLength=null, minLength=null, pattern='null', example='null', jsonSchema='{
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"format" : "int32"
|
"format" : "int32"
|
||||||
}', minimum='null', maximum='null', exclusiveMinimum=false, exclusiveMaximum=false, required=false, deprecated=false, hasMoreNonReadOnly=false, isPrimitiveType=true, isModel=false, isContainer=false, isString=false, isNumeric=true, isInteger=true, isShort=true, isLong=false, isUnboundedInteger=false, isNumber=false, isFloat=false, isDouble=false, isDecimal=false, isByteArray=false, isBinary=false, isFile=false, isBoolean=false, isDate=false, isDateTime=false, isUuid=false, isUri=false, isEmail=false, isFreeFormObject=false, isArray=false, isMap=false, isEnum=false, isReadOnly=false, isWriteOnly=false, isNullable=false, isSelfReference=false, isCircularReference=false, isDiscriminator=false, _enum=null, allowableValues=null, items=null, additionalProperties=null, vars=[], requiredVars=[], mostInnerItems=null, vendorExtensions={}, hasValidation=false, isInherited=false, discriminatorValue='null', nameInCamelCase='XRateLimit', nameInSnakeCase='X_RATE_LIMIT', enumName='null', maxItems=null, minItems=null, maxProperties=null, minProperties=null, uniqueItems=false, multipleOf=null, isXmlAttribute=false, xmlPrefix='null', xmlName='null', xmlNamespace='null', isXmlWrapped=false, isNull=false, getAdditionalPropertiesIsAnyType=false, getHasVars=false, getHasRequired=false, getHasDiscriminatorWithNonEmptyMapping=false, composedSchemas=null, hasMultipleTypes=false}, CodegenProperty{openApiType='string', baseName='X-Expires-After', complexType='Date', getter='getxExpiresAfter', setter='setxExpiresAfter', description='date in UTC when token expires', dataType='Date', datatypeWithEnum='Date', dataFormat='date-time', name='xExpiresAfter', min='null', max='null', defaultValue='null', defaultValueWithParam=' = data.X-Expires-After;', baseType='Date', containerType='null', title='null', unescapedDescription='date in UTC when token expires', maxLength=null, minLength=null, pattern='null', example='null', jsonSchema='{
|
}', minimum='null', maximum='null', exclusiveMinimum=false, exclusiveMaximum=false, required=false, deprecated=false, hasMoreNonReadOnly=false, isPrimitiveType=true, isModel=false, isContainer=false, isString=false, isNumeric=true, isInteger=true, isShort=true, isLong=false, isUnboundedInteger=false, isNumber=false, isFloat=false, isDouble=false, isDecimal=false, isByteArray=false, isBinary=false, isFile=false, isBoolean=false, isDate=false, isDateTime=false, isUuid=false, isUri=false, isEmail=false, isFreeFormObject=false, isArray=false, isMap=false, isEnum=false, isAnyType=false, isReadOnly=false, isWriteOnly=false, isNullable=false, isSelfReference=false, isCircularReference=false, isDiscriminator=false, _enum=null, allowableValues=null, items=null, additionalProperties=null, vars=[], requiredVars=[], mostInnerItems=null, vendorExtensions={}, hasValidation=false, isInherited=false, discriminatorValue='null', nameInCamelCase='XRateLimit', nameInSnakeCase='X_RATE_LIMIT', enumName='null', maxItems=null, minItems=null, maxProperties=null, minProperties=null, uniqueItems=false, multipleOf=null, isXmlAttribute=false, xmlPrefix='null', xmlName='null', xmlNamespace='null', isXmlWrapped=false, isNull=false, getAdditionalPropertiesIsAnyType=false, getHasVars=false, getHasRequired=false, getHasDiscriminatorWithNonEmptyMapping=false, composedSchemas=null, hasMultipleTypes=false}, CodegenProperty{openApiType='string', baseName='X-Expires-After', complexType='Date', getter='getxExpiresAfter', setter='setxExpiresAfter', description='date in UTC when token expires', dataType='Date', datatypeWithEnum='Date', dataFormat='date-time', name='xExpiresAfter', min='null', max='null', defaultValue='null', defaultValueWithParam=' = data.X-Expires-After;', baseType='Date', containerType='null', title='null', unescapedDescription='date in UTC when token expires', maxLength=null, minLength=null, pattern='null', example='null', jsonSchema='{
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"format" : "date-time"
|
"format" : "date-time"
|
||||||
}', minimum='null', maximum='null', exclusiveMinimum=false, exclusiveMaximum=false, required=false, deprecated=false, hasMoreNonReadOnly=false, isPrimitiveType=false, isModel=false, isContainer=false, isString=false, isNumeric=false, isInteger=false, isShort=false, isLong=false, isUnboundedInteger=false, isNumber=false, isFloat=false, isDouble=false, isDecimal=false, isByteArray=false, isBinary=false, isFile=false, isBoolean=false, isDate=false, isDateTime=true, isUuid=false, isUri=false, isEmail=false, isFreeFormObject=false, isArray=false, isMap=false, isEnum=false, isReadOnly=false, isWriteOnly=false, isNullable=false, isSelfReference=false, isCircularReference=false, isDiscriminator=false, _enum=null, allowableValues=null, items=null, additionalProperties=null, vars=[], requiredVars=[], mostInnerItems=null, vendorExtensions={}, hasValidation=false, isInherited=false, discriminatorValue='null', nameInCamelCase='XExpiresAfter', nameInSnakeCase='X_EXPIRES_AFTER', enumName='null', maxItems=null, minItems=null, maxProperties=null, minProperties=null, uniqueItems=false, multipleOf=null, isXmlAttribute=false, xmlPrefix='null', xmlName='null', xmlNamespace='null', isXmlWrapped=false, isNull=false, getAdditionalPropertiesIsAnyType=false, getHasVars=false, getHasRequired=false, getHasDiscriminatorWithNonEmptyMapping=false, composedSchemas=null, hasMultipleTypes=false}]</p>
|
}', minimum='null', maximum='null', exclusiveMinimum=false, exclusiveMaximum=false, required=false, deprecated=false, hasMoreNonReadOnly=false, isPrimitiveType=false, isModel=false, isContainer=false, isString=false, isNumeric=false, isInteger=false, isShort=false, isLong=false, isUnboundedInteger=false, isNumber=false, isFloat=false, isDouble=false, isDecimal=false, isByteArray=false, isBinary=false, isFile=false, isBoolean=false, isDate=false, isDateTime=true, isUuid=false, isUri=false, isEmail=false, isFreeFormObject=false, isArray=false, isMap=false, isEnum=false, isAnyType=false, isReadOnly=false, isWriteOnly=false, isNullable=false, isSelfReference=false, isCircularReference=false, isDiscriminator=false, _enum=null, allowableValues=null, items=null, additionalProperties=null, vars=[], requiredVars=[], mostInnerItems=null, vendorExtensions={}, hasValidation=false, isInherited=false, discriminatorValue='null', nameInCamelCase='XExpiresAfter', nameInSnakeCase='X_EXPIRES_AFTER', enumName='null', maxItems=null, minItems=null, maxProperties=null, minProperties=null, uniqueItems=false, multipleOf=null, isXmlAttribute=false, xmlPrefix='null', xmlName='null', xmlNamespace='null', isXmlWrapped=false, isNull=false, getAdditionalPropertiesIsAnyType=false, getHasVars=false, getHasRequired=false, getHasDiscriminatorWithNonEmptyMapping=false, composedSchemas=null, hasMultipleTypes=false}]</p>
|
||||||
*
|
*
|
||||||
* <p><b>Produces</b>: [{mediaType=application/xml}, {mediaType=application/json}]</p>
|
* <p><b>Produces</b>: [{mediaType=application/xml}, {mediaType=application/json}]</p>
|
||||||
* <p><b>Returns</b>: {@link String}</p>
|
* <p><b>Returns</b>: {@link String}</p>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user