Skip to content

[typescript-fetch] oneOf models now consider primitives when converting. Issue #21259 #21464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,11 @@ private ExtendedCodegenModel processCodeGenModel(ExtendedCodegenModel cm) {
.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()
Expand Down Expand Up @@ -1484,6 +1489,8 @@ public class ExtendedCodegenModel extends CodegenModel {
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,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}}
}
Expand Down Expand Up @@ -112,7 +169,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}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,39 @@ public void givenObjectHasAdditionalPropertiesWhenGenerateThenIndexSignatureNotU
TestUtils.assertFileContains(exampleApiPath, "new Blob([JSON.stringify(ResponseOfStringToJSON");
}

@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();
Expand Down
62 changes: 62 additions & 0 deletions modules/openapi-generator/src/test/resources/bugs/issue_21259.yaml
Original file line number Diff line number Diff line change
@@ -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'
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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 {};
}

Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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