mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-07-05 07:01:01 +00:00
* Fix Issue #21051 * Renamed Test to avoid being overriden by JUnit import * Test fix
This commit is contained in:
parent
c4dad53455
commit
c6a88eaf8e
@ -18,7 +18,9 @@
|
|||||||
package org.openapitools.codegen.languages;
|
package org.openapitools.codegen.languages;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.samskivert.mustache.Mustache;
|
import com.samskivert.mustache.Mustache;
|
||||||
@ -1399,7 +1401,74 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
|
|||||||
return null;
|
return null;
|
||||||
} else if (ModelUtils.isObjectSchema(schema)) {
|
} else if (ModelUtils.isObjectSchema(schema)) {
|
||||||
if (schema.getDefault() != null) {
|
if (schema.getDefault() != null) {
|
||||||
return super.toDefaultValue(schema);
|
try {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
stringBuilder.append("new " + cp.datatypeWithEnum + "()");
|
||||||
|
Map<String, Schema> propertySchemas = schema.getProperties();
|
||||||
|
if(propertySchemas != null) {
|
||||||
|
// With `parseOptions.setResolve(true)`, objects with 1 key-value pair are LinkedHashMap and objects with more than 1 are ObjectNode
|
||||||
|
// When not set, objects of any size are ObjectNode
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
ObjectNode objectNode;
|
||||||
|
if(!(schema.getDefault() instanceof ObjectNode)) {
|
||||||
|
objectNode = objectMapper.valueToTree(schema.getDefault());
|
||||||
|
} else {
|
||||||
|
objectNode = (ObjectNode) schema.getDefault();
|
||||||
|
|
||||||
|
}
|
||||||
|
Set<Map.Entry<String, JsonNode>> defaultProperties = objectNode.properties();
|
||||||
|
for (Map.Entry<String, JsonNode> defaultProperty : defaultProperties) {
|
||||||
|
String key = defaultProperty.getKey();
|
||||||
|
JsonNode value = defaultProperty.getValue();
|
||||||
|
Schema propertySchema = propertySchemas.get(key);
|
||||||
|
if (!value.isValueNode() || propertySchema == null) { //Skip complex objects for now
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String defaultPropertyExpression = null;
|
||||||
|
if(ModelUtils.isLongSchema(propertySchema)) {
|
||||||
|
defaultPropertyExpression = value.asText()+"l";
|
||||||
|
} else if(ModelUtils.isIntegerSchema(propertySchema)) {
|
||||||
|
defaultPropertyExpression = value.asText();
|
||||||
|
} else if(ModelUtils.isDoubleSchema(propertySchema)) {
|
||||||
|
defaultPropertyExpression = value.asText()+"d";
|
||||||
|
} else if(ModelUtils.isFloatSchema(propertySchema)) {
|
||||||
|
defaultPropertyExpression = value.asText()+"f";
|
||||||
|
} else if(ModelUtils.isNumberSchema(propertySchema)) {
|
||||||
|
defaultPropertyExpression = "new java.math.BigDecimal(\"" + value.asText() + "\")";
|
||||||
|
} else if(ModelUtils.isURISchema(propertySchema)) {
|
||||||
|
defaultPropertyExpression = "java.net.URI.create(\"" + escapeText(value.asText()) + "\")";
|
||||||
|
} else if(ModelUtils.isDateSchema(propertySchema)) {
|
||||||
|
if("java8".equals(getDateLibrary())) {
|
||||||
|
defaultPropertyExpression = String.format(Locale.ROOT, "java.time.LocalDate.parse(\"%s\")", value.asText());
|
||||||
|
}
|
||||||
|
} else if(ModelUtils.isDateTimeSchema(propertySchema)) {
|
||||||
|
if("java8".equals(getDateLibrary())) {
|
||||||
|
defaultPropertyExpression = String.format(Locale.ROOT, "java.time.OffsetDateTime.parse(\"%s\", %s)",
|
||||||
|
value.asText(),
|
||||||
|
"java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME.withZone(java.time.ZoneId.systemDefault())");
|
||||||
|
}
|
||||||
|
} else if(ModelUtils.isUUIDSchema(propertySchema)) {
|
||||||
|
defaultPropertyExpression = "java.util.UUID.fromString(\"" + value.asText() + "\")";
|
||||||
|
} else if(ModelUtils.isStringSchema(propertySchema)) {
|
||||||
|
defaultPropertyExpression = "\"" + value.asText() + "\"";
|
||||||
|
} else if(ModelUtils.isBooleanSchema(propertySchema)) {
|
||||||
|
defaultPropertyExpression = value.asText();
|
||||||
|
}
|
||||||
|
if(defaultPropertyExpression != null) {
|
||||||
|
stringBuilder
|
||||||
|
// .append(System.lineSeparator())
|
||||||
|
.append(".")
|
||||||
|
.append(toVarName(key))
|
||||||
|
.append("(").append(defaultPropertyExpression).append(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
LOGGER.error("Can't resolve default value: "+schema.getDefault(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} else if (ModelUtils.isComposedSchema(schema)) {
|
} else if (ModelUtils.isComposedSchema(schema)) {
|
||||||
|
@ -17,6 +17,12 @@
|
|||||||
|
|
||||||
package org.openapitools.codegen.java;
|
package org.openapitools.codegen.java;
|
||||||
|
|
||||||
|
import com.github.javaparser.StaticJavaParser;
|
||||||
|
import com.github.javaparser.ast.CompilationUnit;
|
||||||
|
import com.github.javaparser.ast.body.FieldDeclaration;
|
||||||
|
import com.github.javaparser.ast.expr.Expression;
|
||||||
|
import com.github.javaparser.ast.expr.MethodCallExpr;
|
||||||
|
import com.github.javaparser.ast.visitor.*;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import io.swagger.parser.OpenAPIParser;
|
import io.swagger.parser.OpenAPIParser;
|
||||||
import io.swagger.v3.oas.models.OpenAPI;
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
@ -60,7 +66,7 @@ import java.util.stream.Collectors;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.entry;
|
import static org.assertj.core.api.Assertions.entry;
|
||||||
import static org.assertj.core.api.InstanceOfAssertFactories.FILE;
|
import static org.assertj.core.api.InstanceOfAssertFactories.FILE;
|
||||||
import static org.openapitools.codegen.CodegenConstants.SERIALIZATION_LIBRARY;
|
import static org.openapitools.codegen.CodegenConstants.*;
|
||||||
import static org.openapitools.codegen.TestUtils.newTempFolder;
|
import static org.openapitools.codegen.TestUtils.newTempFolder;
|
||||||
import static org.openapitools.codegen.TestUtils.validateJavaSourceFiles;
|
import static org.openapitools.codegen.TestUtils.validateJavaSourceFiles;
|
||||||
import static org.openapitools.codegen.languages.JavaClientCodegen.*;
|
import static org.openapitools.codegen.languages.JavaClientCodegen.*;
|
||||||
@ -3592,4 +3598,71 @@ public class JavaClientCodegenTest {
|
|||||||
"public some.pkg.B getsomepkgB() throws ClassCastException {"
|
"public some.pkg.B getsomepkgB() throws ClassCastException {"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(description = "Issue #21051")
|
||||||
|
public void givenComplexObjectHasDefaultValueWhenGenerateThenDefaultAssignmentsAreValid() throws Exception {
|
||||||
|
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
|
||||||
|
output.deleteOnExit();
|
||||||
|
|
||||||
|
Map<String, Object> properties = new HashMap<>();
|
||||||
|
properties.put(APIS, false);
|
||||||
|
properties.put(API_DOCS, false);
|
||||||
|
properties.put(API_TESTS, false);
|
||||||
|
properties.put(MODEL_DOCS, false);
|
||||||
|
properties.put(MODEL_TESTS, false);
|
||||||
|
|
||||||
|
Generator generator = new DefaultGenerator();
|
||||||
|
CodegenConfigurator configurator = new CodegenConfigurator()
|
||||||
|
.setInputSpec("src/test/resources/3_1/issue_21051.yaml")
|
||||||
|
.setGeneratorName("java")
|
||||||
|
.setAdditionalProperties(properties)
|
||||||
|
.setOutputDir(output.getAbsolutePath());
|
||||||
|
ClientOptInput clientOptInput = configurator.toClientOptInput();
|
||||||
|
generator.opts(clientOptInput)
|
||||||
|
.generate();
|
||||||
|
System.out.println("Generator Settings: " + clientOptInput.getGeneratorSettings());
|
||||||
|
String outputPath = output.getAbsolutePath() + "/src/main/java/org/openapitools";
|
||||||
|
File testModel = new File(outputPath, "/client/model/TestCase.java");
|
||||||
|
String fileContent = Files.readString(testModel.toPath());
|
||||||
|
|
||||||
|
System.out.println(fileContent);
|
||||||
|
TestUtils.assertValidJavaSourceCode(fileContent);
|
||||||
|
CompilationUnit compilationUnit = StaticJavaParser.parse(testModel);
|
||||||
|
Map<String, FieldDeclaration> defaultFields = compilationUnit.getType(0).getFields().stream()
|
||||||
|
.collect(Collectors.toMap((f) -> f.getVariable(0).getName().asString(), (f) -> f));
|
||||||
|
//chain method calls for object initialization
|
||||||
|
class MethodCallVisitor extends VoidVisitorAdapter<Void> {
|
||||||
|
Map<String, Expression> expressionMap = new HashMap<>();
|
||||||
|
@Override
|
||||||
|
public void visit(MethodCallExpr n, Void arg) {
|
||||||
|
expressionMap.put(n.getNameAsString(), n.getArgument(0));
|
||||||
|
if(n.getScope().isPresent()) {
|
||||||
|
n.getScope().get().accept(this, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
MethodCallVisitor visitor = new MethodCallVisitor();
|
||||||
|
defaultFields.get("testComplexInlineObject").getVariable(0).getInitializer().get().asMethodCallExpr()
|
||||||
|
.accept(visitor, null);
|
||||||
|
Map<String, Expression> expressionMap = visitor.expressionMap;
|
||||||
|
assertTrue(expressionMap.get("foo").isStringLiteralExpr());
|
||||||
|
assertTrue(expressionMap.get("fooInt").isIntegerLiteralExpr());
|
||||||
|
assertTrue(expressionMap.get("fooLong").isLongLiteralExpr());
|
||||||
|
assertTrue(expressionMap.get("fooBool").isBooleanLiteralExpr());
|
||||||
|
assertTrue(expressionMap.get("fooFloat").isDoubleLiteralExpr());
|
||||||
|
assertTrue(expressionMap.get("fooDouble").isDoubleLiteralExpr());
|
||||||
|
assertTrue(expressionMap.containsKey("_void"));
|
||||||
|
|
||||||
|
assertFalse(expressionMap.containsKey("nonExistentDefault"));
|
||||||
|
assertFalse(expressionMap.containsKey("nonDefaultedProperty"));
|
||||||
|
|
||||||
|
assertTrue(defaultFields.get("testEmptyInlineObject").getVariable(0).getInitializer().get().isObjectCreationExpr());
|
||||||
|
assertTrue(defaultFields.get("testNullableEmptyInlineObject").getVariable(0).getInitializer().get().isObjectCreationExpr());
|
||||||
|
assertTrue(defaultFields.get("testNullableComplexInlineObject").getVariable(0).getInitializer().get().isMethodCallExpr());
|
||||||
|
assertTrue(defaultFields.get("testEmptyReference").getVariable(0).getInitializer().get().isObjectCreationExpr());
|
||||||
|
assertTrue(defaultFields.get("testComplexReference").getVariable(0).getInitializer().get().isMethodCallExpr());
|
||||||
|
assertTrue(defaultFields.get("testNullableEmptyReference").getVariable(0).getInitializer().get().isObjectCreationExpr());
|
||||||
|
assertTrue(defaultFields.get("testNullableComplexReference").getVariable(0).getInitializer().get().isMethodCallExpr());
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
# Modified from the original
|
||||||
|
openapi: 3.1.0
|
||||||
|
info:
|
||||||
|
title: Petstore API
|
||||||
|
description: Petstore API
|
||||||
|
version: 1.0.0
|
||||||
|
servers:
|
||||||
|
- url: 'http://localhost'
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
# Not generated - free-form object
|
||||||
|
EmptyReferenceObject:
|
||||||
|
type: object
|
||||||
|
default: {}
|
||||||
|
ComplexReferenceObject:
|
||||||
|
type: object
|
||||||
|
default:
|
||||||
|
foo: bar
|
||||||
|
properties:
|
||||||
|
foo:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
NullableEmptyReferenceObject:
|
||||||
|
type: object
|
||||||
|
default: {}
|
||||||
|
nullable: true
|
||||||
|
NullableComplexReferenceObject:
|
||||||
|
type: object
|
||||||
|
default:
|
||||||
|
foo: bar
|
||||||
|
properties:
|
||||||
|
foo:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
nullable: true
|
||||||
|
TestCase:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
testEmptyInlineObject:
|
||||||
|
type: object
|
||||||
|
default: {}
|
||||||
|
testComplexInlineObject:
|
||||||
|
type: object
|
||||||
|
default:
|
||||||
|
foo: bar
|
||||||
|
fooInt: 28
|
||||||
|
fooLong: 5000000000
|
||||||
|
fooBool: true
|
||||||
|
fooFloat: 32.5
|
||||||
|
fooDouble: 3332.555
|
||||||
|
fooNumber: 120.6
|
||||||
|
fooDateTime: "2000-01-01T20:20:20+00:00"
|
||||||
|
fooUUID: "a0ed70ec-5fe5-415a-be97-a7bf13db9fb6"
|
||||||
|
void: empty
|
||||||
|
nonExistentDefault: 27
|
||||||
|
properties:
|
||||||
|
foo:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
fooInt:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
|
fooLong:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
nullable: true
|
||||||
|
fooBool:
|
||||||
|
type: boolean
|
||||||
|
fooFloat:
|
||||||
|
type: number
|
||||||
|
format: float
|
||||||
|
nullable: true
|
||||||
|
fooDouble:
|
||||||
|
type: number
|
||||||
|
format: double
|
||||||
|
nullable: true
|
||||||
|
fooNumber:
|
||||||
|
type: number
|
||||||
|
nullable: true
|
||||||
|
fooDateTime:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
nullable: true
|
||||||
|
fooUUID:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
void: # Java keyword
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
nonDefaultedProperty:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
testNullableEmptyInlineObject:
|
||||||
|
type: object
|
||||||
|
default: {}
|
||||||
|
nullable: true
|
||||||
|
testNullableComplexInlineObject:
|
||||||
|
type: object
|
||||||
|
default:
|
||||||
|
foo: bar
|
||||||
|
properties:
|
||||||
|
foo:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
nullable: true
|
||||||
|
testEmptyReference:
|
||||||
|
$ref: '#/components/schemas/EmptyReferenceObject'
|
||||||
|
testComplexReference:
|
||||||
|
$ref: '#/components/schemas/ComplexReferenceObject'
|
||||||
|
testNullableEmptyReference:
|
||||||
|
$ref: '#/components/schemas/NullableEmptyReferenceObject'
|
||||||
|
testNullableComplexReference:
|
||||||
|
$ref: '#/components/schemas/NullableComplexReferenceObject'
|
Loading…
x
Reference in New Issue
Block a user