Skip to content

Commit e003116

Browse files
author
kshramt
committed
Support free-form objects
> A free-form object (arbitrary property/value pairs) is defined as: > > type: object > > This is equivalent to > > type: object > additionalProperties: true > > and > > type: object > additionalProperties: {} https://swagger.io/docs/specification/data-models/data-types/
1 parent c56306a commit e003116

File tree

3 files changed

+125
-13
lines changed

3 files changed

+125
-13
lines changed

src/openApi/v3/parser/getModel.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,13 @@ export const getModel = (
9595
}
9696
}
9797

98-
if (definition.type === 'object' && typeof definition.additionalProperties === 'object') {
99-
if (definition.additionalProperties.$ref) {
100-
const additionalProperties = getType(definition.additionalProperties.$ref);
98+
if (
99+
definition.type === 'object' &&
100+
(typeof definition.additionalProperties === 'object' || definition.additionalProperties === true)
101+
) {
102+
const ap = typeof definition.additionalProperties === 'object' ? definition.additionalProperties : {};
103+
if (ap.$ref) {
104+
const additionalProperties = getType(ap.$ref);
101105
model.export = 'dictionary';
102106
model.type = additionalProperties.type;
103107
model.base = additionalProperties.base;
@@ -106,7 +110,7 @@ export const getModel = (
106110
model.default = getModelDefault(definition, model);
107111
return model;
108112
} else {
109-
const additionalProperties = getModel(openApi, definition.additionalProperties);
113+
const additionalProperties = getModel(openApi, ap);
110114
model.export = 'dictionary';
111115
model.type = additionalProperties.type;
112116
model.base = additionalProperties.base;
@@ -146,12 +150,12 @@ export const getModel = (
146150
}
147151

148152
if (definition.type === 'object') {
149-
model.export = 'interface';
150-
model.type = 'any';
151-
model.base = 'any';
152-
model.default = getModelDefault(definition, model);
153-
154153
if (definition.properties) {
154+
model.export = 'interface';
155+
model.type = 'any';
156+
model.base = 'any';
157+
model.default = getModelDefault(definition, model);
158+
155159
const modelProperties = getModelProperties(openApi, definition, getModel, model);
156160
modelProperties.forEach(modelProperty => {
157161
model.imports.push(...modelProperty.imports);
@@ -161,8 +165,18 @@ export const getModel = (
161165
model.enums.push(modelProperty);
162166
}
163167
});
168+
return model;
169+
} else {
170+
const additionalProperties = getModel(openApi, {});
171+
model.export = 'dictionary';
172+
model.type = additionalProperties.type;
173+
model.base = additionalProperties.base;
174+
model.template = additionalProperties.template;
175+
model.link = additionalProperties;
176+
model.imports.push(...additionalProperties.imports);
177+
model.default = getModelDefault(definition, model);
178+
return model;
164179
}
165-
return model;
166180
}
167181

168182
// If the schema has a type than it can be a basic or generic type.

test/__snapshots__/index.spec.ts.snap

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3643,6 +3643,9 @@ export { EnumWithExtensions } from './models/EnumWithExtensions';
36433643
export { EnumWithNumbers } from './models/EnumWithNumbers';
36443644
export { EnumWithStrings } from './models/EnumWithStrings';
36453645
export type { File } from './models/File';
3646+
export type { FreeFormObjectWithAdditionalPropertiesEqEmptyObject } from './models/FreeFormObjectWithAdditionalPropertiesEqEmptyObject';
3647+
export type { FreeFormObjectWithAdditionalPropertiesEqTrue } from './models/FreeFormObjectWithAdditionalPropertiesEqTrue';
3648+
export type { FreeFormObjectWithoutAdditionalProperties } from './models/FreeFormObjectWithoutAdditionalProperties';
36463649
export type { ModelCircle } from './models/ModelCircle';
36473650
export type { ModelSquare } from './models/ModelSquare';
36483651
export type { ModelThatExtends } from './models/ModelThatExtends';
@@ -3708,6 +3711,9 @@ export { $EnumWithExtensions } from './schemas/$EnumWithExtensions';
37083711
export { $EnumWithNumbers } from './schemas/$EnumWithNumbers';
37093712
export { $EnumWithStrings } from './schemas/$EnumWithStrings';
37103713
export { $File } from './schemas/$File';
3714+
export { $FreeFormObjectWithAdditionalPropertiesEqEmptyObject } from './schemas/$FreeFormObjectWithAdditionalPropertiesEqEmptyObject';
3715+
export { $FreeFormObjectWithAdditionalPropertiesEqTrue } from './schemas/$FreeFormObjectWithAdditionalPropertiesEqTrue';
3716+
export { $FreeFormObjectWithoutAdditionalProperties } from './schemas/$FreeFormObjectWithoutAdditionalProperties';
37113717
export { $ModelCircle } from './schemas/$ModelCircle';
37123718
export { $ModelSquare } from './schemas/$ModelSquare';
37133719
export { $ModelThatExtends } from './schemas/$ModelThatExtends';
@@ -4334,6 +4340,42 @@ export type File = {
43344340
"
43354341
`;
43364342

4343+
exports[`v3 should generate: ./test/generated/v3/models/FreeFormObjectWithAdditionalPropertiesEqEmptyObject.ts 1`] = `
4344+
"/* istanbul ignore file */
4345+
/* tslint:disable */
4346+
/* eslint-disable */
4347+
4348+
/**
4349+
* This is a free-form object with additionalProperties: {}.
4350+
*/
4351+
export type FreeFormObjectWithAdditionalPropertiesEqEmptyObject = Record<string, any>;
4352+
"
4353+
`;
4354+
4355+
exports[`v3 should generate: ./test/generated/v3/models/FreeFormObjectWithAdditionalPropertiesEqTrue.ts 1`] = `
4356+
"/* istanbul ignore file */
4357+
/* tslint:disable */
4358+
/* eslint-disable */
4359+
4360+
/**
4361+
* This is a free-form object with additionalProperties: true.
4362+
*/
4363+
export type FreeFormObjectWithAdditionalPropertiesEqTrue = Record<string, any>;
4364+
"
4365+
`;
4366+
4367+
exports[`v3 should generate: ./test/generated/v3/models/FreeFormObjectWithoutAdditionalProperties.ts 1`] = `
4368+
"/* istanbul ignore file */
4369+
/* tslint:disable */
4370+
/* eslint-disable */
4371+
4372+
/**
4373+
* This is a free-form object without additionalProperties.
4374+
*/
4375+
export type FreeFormObjectWithoutAdditionalProperties = Record<string, any>;
4376+
"
4377+
`;
4378+
43374379
exports[`v3 should generate: ./test/generated/v3/models/ModelCircle.ts 1`] = `
43384380
"/* istanbul ignore file */
43394381
/* tslint:disable */
@@ -5514,6 +5556,48 @@ export const $File = {
55145556
"
55155557
`;
55165558

5559+
exports[`v3 should generate: ./test/generated/v3/schemas/$FreeFormObjectWithAdditionalPropertiesEqEmptyObject.ts 1`] = `
5560+
"/* istanbul ignore file */
5561+
/* tslint:disable */
5562+
/* eslint-disable */
5563+
export const $FreeFormObjectWithAdditionalPropertiesEqEmptyObject = {
5564+
type: 'dictionary',
5565+
contains: {
5566+
properties: {
5567+
},
5568+
},
5569+
} as const;
5570+
"
5571+
`;
5572+
5573+
exports[`v3 should generate: ./test/generated/v3/schemas/$FreeFormObjectWithAdditionalPropertiesEqTrue.ts 1`] = `
5574+
"/* istanbul ignore file */
5575+
/* tslint:disable */
5576+
/* eslint-disable */
5577+
export const $FreeFormObjectWithAdditionalPropertiesEqTrue = {
5578+
type: 'dictionary',
5579+
contains: {
5580+
properties: {
5581+
},
5582+
},
5583+
} as const;
5584+
"
5585+
`;
5586+
5587+
exports[`v3 should generate: ./test/generated/v3/schemas/$FreeFormObjectWithoutAdditionalProperties.ts 1`] = `
5588+
"/* istanbul ignore file */
5589+
/* tslint:disable */
5590+
/* eslint-disable */
5591+
export const $FreeFormObjectWithoutAdditionalProperties = {
5592+
type: 'dictionary',
5593+
contains: {
5594+
properties: {
5595+
},
5596+
},
5597+
} as const;
5598+
"
5599+
`;
5600+
55175601
exports[`v3 should generate: ./test/generated/v3/schemas/$ModelCircle.ts 1`] = `
55185602
"/* istanbul ignore file */
55195603
/* tslint:disable */
@@ -7148,14 +7232,14 @@ export class TypesService {
71487232
*/
71497233
public static types(
71507234
parameterArray: Array<string> | null,
7151-
parameterDictionary: any,
7235+
parameterDictionary: Record<string, any> | null,
71527236
parameterEnum: 'Success' | 'Warning' | 'Error' | null,
71537237
parameterNumber: number = 123,
71547238
parameterString: string | null = 'default',
71557239
parameterBoolean: boolean | null = true,
7156-
parameterObject: any = null,
7240+
parameterObject: Record<string, any> | null = null,
71577241
id?: number,
7158-
): CancelablePromise<number | string | boolean | any> {
7242+
): CancelablePromise<number | string | boolean | Record<string, any>> {
71597243
return __request(OpenAPI, {
71607244
method: 'GET',
71617245
url: '/api/v{api-version}/types',

test/spec/v3.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,6 +2527,20 @@
25272527
}
25282528
}
25292529
}
2530+
},
2531+
"FreeFormObjectWithoutAdditionalProperties": {
2532+
"description": "This is a free-form object without additionalProperties.",
2533+
"type": "object"
2534+
},
2535+
"FreeFormObjectWithAdditionalPropertiesEqTrue": {
2536+
"description": "This is a free-form object with additionalProperties: true.",
2537+
"type": "object",
2538+
"additionalProperties": true
2539+
},
2540+
"FreeFormObjectWithAdditionalPropertiesEqEmptyObject": {
2541+
"description": "This is a free-form object with additionalProperties: {}.",
2542+
"type": "object",
2543+
"additionalProperties": {}
25302544
}
25312545
}
25322546
}

0 commit comments

Comments
 (0)