mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-10-13 16:03:43 +00:00
* [typescript-fetch] number, string, and Date now considered in oneOf models. Issue #21259 * Generated samples
This commit is contained in:
parent
777b7eeea0
commit
f1a093537d
@ -799,6 +799,11 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toCollection(TreeSet::new));
|
||||
|
||||
cm.oneOfPrimitives = oneOfsList.stream()
|
||||
.filter(CodegenProperty::getIsPrimitiveType)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
|
||||
if (!cm.oneOf.isEmpty()) {
|
||||
// For oneOfs only import $refs within the oneOf
|
||||
cm.imports = cm.imports.stream()
|
||||
@ -1484,6 +1489,8 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
|
||||
public Set<String> oneOfModels = new TreeSet<>();
|
||||
@Getter @Setter
|
||||
public Set<String> oneOfArrays = new TreeSet<>();
|
||||
@Getter @Setter
|
||||
public Set<CodegenProperty> oneOfPrimitives = new HashSet<>();
|
||||
|
||||
public boolean isEntity; // Is a model containing an "id" property marked as isUniqueId
|
||||
public String returnPassthrough;
|
||||
|
@ -65,7 +65,64 @@ export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boole
|
||||
}
|
||||
{{/-last}}
|
||||
{{/oneOfArrays}}
|
||||
|
||||
{{#oneOfPrimitives}}
|
||||
{{#isArray}}
|
||||
{{#items}}
|
||||
{{#isDateType}}
|
||||
if (Array.isArray(json)) {
|
||||
if (json.every(item => !(isNaN(new Date(json).getTime()))) {
|
||||
return json.map(value => new Date(json);
|
||||
}
|
||||
}
|
||||
{{/isDateType}}
|
||||
{{#isDateTimeType}}
|
||||
if (Array.isArray(json)) {
|
||||
if (json.every(item => !(isNaN(new Date(json).getTime()))) {
|
||||
return json.map(value => new Date(json);
|
||||
}
|
||||
}
|
||||
{{/isDateTimeType}}
|
||||
{{#isNumeric}}
|
||||
if (Array.isArray(json)) {
|
||||
if (json.every(item => typeof item === 'number'{{#isEnum}} && ({{#allowableValues}}{{#values}}item === {{.}}{{^-last}} || {{/-last}}{{/values}}{{/allowableValues}}){{/isEnum}})) {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
{{/isNumeric}}
|
||||
{{#isString}}
|
||||
if (Array.isArray(json)) {
|
||||
if (json.every(item => typeof item === 'string'{{#isEnum}} && ({{#allowableValues}}{{#values}}item === '{{.}}'{{^-last}} || {{/-last}}{{/values}}{{/allowableValues}}){{/isEnum}})) {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
{{/isString}}
|
||||
{{/items}}
|
||||
{{/isArray}}
|
||||
{{^isArray}}
|
||||
{{#isDateType}}
|
||||
if(!(isNaN(new Date(json).getTime()))) {
|
||||
return {{^required}}json == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json == null ? null : {{/isNullable}}{{/required}}new Date(json));
|
||||
}
|
||||
{{/isDateType}}
|
||||
{{^isDateType}}
|
||||
{{#isDateTimeType}}
|
||||
if(!(isNaN(new Date(json).getTime()))) {
|
||||
return {{^required}}json == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json == null ? null : {{/isNullable}}{{/required}}new Date(json));
|
||||
}
|
||||
{{/isDateTimeType}}
|
||||
{{/isDateType}}
|
||||
{{#isNumeric}}
|
||||
if(typeof json === 'number'{{#isEnum}} && ({{#allowableValues}}{{#values}}json === {{.}}{{^-last}} || {{/-last}}{{/values}}{{/allowableValues}}){{/isEnum}}) {
|
||||
return json;
|
||||
}
|
||||
{{/isNumeric}}
|
||||
{{#isString}}
|
||||
if(typeof json === 'string'{{#isEnum}} && ({{#allowableValues}}{{#values}}json === '{{.}}'{{^-last}} || {{/-last}}{{/values}}{{/allowableValues}}){{/isEnum}}) {
|
||||
return json;
|
||||
}
|
||||
{{/isString}}
|
||||
{{/isArray}}
|
||||
{{/oneOfPrimitives}}
|
||||
return {} as any;
|
||||
{{/discriminator}}
|
||||
}
|
||||
@ -113,7 +170,62 @@ export function {{classname}}ToJSONTyped(value?: {{classname}} | null, ignoreDis
|
||||
}
|
||||
{{/-last}}
|
||||
{{/oneOfArrays}}
|
||||
|
||||
{{#oneOfPrimitives}}
|
||||
{{#isArray}}
|
||||
{{#items}}
|
||||
{{#isDateType}}
|
||||
if (Array.isArray(value)) {
|
||||
if (value.every(item => item instanceof Date) {
|
||||
return value.map(value => value.toISOString().substring(0,10)));
|
||||
}
|
||||
}
|
||||
{{/isDateType}}
|
||||
{{#isDateTimeType}}
|
||||
if (Array.isArray(value)) {
|
||||
if (value.every(item => item instanceof Date) {
|
||||
return value.map(value => value.toISOString();
|
||||
}
|
||||
}
|
||||
{{/isDateTimeType}}
|
||||
{{#isNumeric}}
|
||||
if (Array.isArray(value)) {
|
||||
if (value.every(item => typeof item === 'number'{{#isEnum}} && ({{#allowableValues}}{{#values}}item === {{.}}{{^-last}} || {{/-last}}{{/values}}{{/allowableValues}}){{/isEnum}}) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
{{/isNumeric}}
|
||||
{{#isString}}
|
||||
if (Array.isArray(value)) {
|
||||
if (value.every(item => typeof item === 'string'{{#isEnum}} && ({{#allowableValues}}{{#values}}item === '{{.}}'{{^-last}} || {{/-last}}{{/values}}{{/allowableValues}}){{/isEnum}}) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
{{/isString}}
|
||||
{{/items}}
|
||||
{{/isArray}}
|
||||
{{^isArray}}
|
||||
{{#isDateType}}
|
||||
if(value instanceof Date) {
|
||||
return ((value{{#isNullable}} as any{{/isNullable}}){{^required}}{{#isNullable}}?{{/isNullable}}{{/required}}.toISOString().substring(0,10));
|
||||
}
|
||||
{{/isDateType}}
|
||||
{{#isDateTimeType}}
|
||||
if(value instanceof Date) {
|
||||
return {{^required}}{{#isNullable}}value === null ? null : {{/isNullable}}{{^isNullable}}value == null ? undefined : {{/isNullable}}{{/required}}((value{{#isNullable}} as any{{/isNullable}}){{^required}}{{#isNullable}}?{{/isNullable}}{{/required}}.toISOString());
|
||||
}
|
||||
{{/isDateTimeType}}
|
||||
{{#isNumeric}}
|
||||
if(typeof value === 'number'{{#isEnum}} && ({{#allowableValues}}{{#values}}value === {{.}}{{^-last}} || {{/-last}}{{/values}}{{/allowableValues}}){{/isEnum}}) {
|
||||
return value;
|
||||
}
|
||||
{{/isNumeric}}
|
||||
{{#isString}}
|
||||
if(typeof value === 'string'{{#isEnum}} && ({{#allowableValues}}{{#values}}value === '{{.}}'{{^-last}} || {{/-last}}{{/values}}{{/allowableValues}}){{/isEnum}}) {
|
||||
return value;
|
||||
}
|
||||
{{/isString}}
|
||||
{{/isArray}}
|
||||
{{/oneOfPrimitives}}
|
||||
return {};
|
||||
{{/discriminator}}
|
||||
}
|
||||
|
@ -347,6 +347,39 @@ public class TypeScriptFetchClientCodegenTest {
|
||||
TestUtils.assertFileExists(Paths.get(output + "/apis/petControllerApi.ts"));
|
||||
}
|
||||
|
||||
@Test(description = "Issue #21295")
|
||||
public void givenSchemaIsOneOfAndComposedSchemasArePrimitiveThenReturnStatementsAreCorrect() throws Exception {
|
||||
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
|
||||
output.deleteOnExit();
|
||||
String outputPath = output.getAbsolutePath();
|
||||
|
||||
|
||||
TypeScriptFetchClientCodegen clientCodegen = new TypeScriptFetchClientCodegen();
|
||||
clientCodegen.setOutputDir(outputPath);
|
||||
|
||||
DefaultGenerator defaultGenerator = new DefaultGenerator();
|
||||
defaultGenerator.opts(
|
||||
new ClientOptInput().openAPI(TestUtils.parseSpec("src/test/resources/bugs/issue_21259.yaml"))
|
||||
.config(clientCodegen)
|
||||
).generate();
|
||||
|
||||
Path exampleModelPath = Paths.get(outputPath + "/models/MyCustomSpeed.ts");
|
||||
//FromJSON
|
||||
TestUtils.assertFileContains(exampleModelPath, "typeof json === 'number'");
|
||||
TestUtils.assertFileContains(exampleModelPath, "typeof json === 'string'");
|
||||
TestUtils.assertFileContains(exampleModelPath, "json === 'fixed-value-a' || json === 'fixed-value-b' || json === 'fixed-value-c'");
|
||||
TestUtils.assertFileContains(exampleModelPath, "isNaN(new Date(json).getTime())");
|
||||
TestUtils.assertFileContains(exampleModelPath, "json.every(item => typeof item === 'number'");
|
||||
// TestUtils.assertFileContains(exampleModelPath, "json.every(item => typeof item === 'string' && (item === 'oneof-array-enum-a' || item oneof-array-enum-b || item === oneof-array-enum-c)");
|
||||
//ToJSON
|
||||
TestUtils.assertFileContains(exampleModelPath, "typeof value === 'number'");
|
||||
TestUtils.assertFileContains(exampleModelPath, "typeof value === 'string'");
|
||||
TestUtils.assertFileContains(exampleModelPath, "value === 'fixed-value-a' || value === 'fixed-value-b' || value === 'fixed-value-c'");
|
||||
TestUtils.assertFileContains(exampleModelPath, "value instanceof Date");
|
||||
TestUtils.assertFileContains(exampleModelPath, "value.every(item => typeof item === 'number'");
|
||||
// TestUtils.assertFileContains(exampleModelPath, "value.every(item => typeof item === 'string' && (item === 'oneof-array-enum-a' || item oneof-array-enum-b || item === oneof-array-enum-c)");
|
||||
}
|
||||
|
||||
private static File generate(Map<String, Object> properties) throws IOException {
|
||||
File output = Files.createTempDirectory("test").toFile();
|
||||
output.deleteOnExit();
|
||||
|
@ -0,0 +1,62 @@
|
||||
#Modified from the original
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: Minimal API for Bug Report
|
||||
version: v1
|
||||
paths:
|
||||
/test:
|
||||
post:
|
||||
summary: Test endpoint with MyCustomSpeed
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TestPayload'
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
components:
|
||||
schemas:
|
||||
MyNumericValue:
|
||||
type: object
|
||||
properties:
|
||||
lmnop:
|
||||
type: number
|
||||
description: A numeric value (e.g., 0 to 1).
|
||||
MyCustomSpeed:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/MyNumericValue'
|
||||
- type: string
|
||||
enum:
|
||||
- "fixed-value-a"
|
||||
- "fixed-value-b"
|
||||
- "fixed-value-c"
|
||||
- type: string
|
||||
format: date
|
||||
- type: string
|
||||
format: date-time
|
||||
- type: integer
|
||||
format: int64
|
||||
enum: [10, 20, 30]
|
||||
- type: array
|
||||
items:
|
||||
type: number
|
||||
- type: array
|
||||
items:
|
||||
- type: object
|
||||
- type: array
|
||||
items:
|
||||
- type: string
|
||||
enum:
|
||||
# It seems enums within arrays don't work. Leaving this here, though
|
||||
- "oneof-array-enum-a"
|
||||
- "oneof-array-enum-b"
|
||||
- "oneof-array-enum-c"
|
||||
- type:
|
||||
description: A value that can be a number or a specific string.
|
||||
TestPayload:
|
||||
type: object
|
||||
properties:
|
||||
speed_setting:
|
||||
$ref: '#/components/schemas/MyCustomSpeed'
|
@ -53,7 +53,11 @@ export function TestArrayResponseFromJSONTyped(json: any, ignoreDiscriminator: b
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
if (Array.isArray(json)) {
|
||||
if (json.every(item => typeof item === 'string')) {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
return {} as any;
|
||||
}
|
||||
|
||||
@ -76,7 +80,11 @@ export function TestArrayResponseToJSONTyped(value?: TestArrayResponse | null, i
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
if (value.every(item => typeof item === 'string') {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,9 @@ export function TestResponseFromJSONTyped(json: any, ignoreDiscriminator: boolea
|
||||
if (instanceOfTestB(json)) {
|
||||
return TestBFromJSONTyped(json, true);
|
||||
}
|
||||
|
||||
if(typeof json === 'string') {
|
||||
return json;
|
||||
}
|
||||
return {} as any;
|
||||
}
|
||||
|
||||
@ -72,7 +74,9 @@ export function TestResponseToJSONTyped(value?: TestResponse | null, ignoreDiscr
|
||||
if (instanceOfTestB(value)) {
|
||||
return TestBToJSON(value as TestB);
|
||||
}
|
||||
|
||||
if(typeof value === 'string') {
|
||||
return value;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user