diff --git a/examples/README.md b/examples/README.md index 5e84a61e02..15783225cb 100644 --- a/examples/README.md +++ b/examples/README.md @@ -47,10 +47,10 @@ These examples show a specific input and how they can be used: - [json-schema-draft6-from-object](./json-schema-draft6-from-object) - A basic example where a JSON Schema draft 6 JS object is used to generate models. - [json-schema-draft4-from-object](./json-schema-draft4-from-object) - A basic example where a JSON Schema draft 4 JS object is used to generate models. - [json-schema-single-enum-as-const](./json-schema-single-enum-as-const) - An advanced example that shows how to change how `enum` are interpreted when containing a single value. +- [json-schema-additional-properties-representation](./json-schema-additional-properties-representation) - An advanced example that shows how to change the property name for additional properties - [swagger2.0-from-object](./swagger2.0-from-object) - A basic example where a Swagger 2.0 JS object is used to generate models. - [meta-model](./meta-model) - A basic example how to provide a meta model for the generator - ## General examples These are examples that can be applied in all scenarios. - [include-custom-function](./include-custom-function) - A basic example where a custom function is included. diff --git a/examples/json-schema-additional-properties-representation/README.md b/examples/json-schema-additional-properties-representation/README.md new file mode 100644 index 0000000000..89d2ce5803 --- /dev/null +++ b/examples/json-schema-additional-properties-representation/README.md @@ -0,0 +1,17 @@ +# JSON Schema change property name for additional properties + +This example shows how to use the `propertyNameForAdditionalProperties` option on the JSON Schema input processor to change the property name that is used for representing additional properties. + +## How to run this example + +Run this example using: + +```sh +npm i && npm run start +``` + +If you are on Windows, use the `start:windows` script instead: + +```sh +npm i && npm run start:windows +``` diff --git a/examples/json-schema-additional-properties-representation/__snapshots__/index.spec.ts.snap b/examples/json-schema-additional-properties-representation/__snapshots__/index.spec.ts.snap new file mode 100644 index 0000000000..8226953cb1 --- /dev/null +++ b/examples/json-schema-additional-properties-representation/__snapshots__/index.spec.ts.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Should be able to render object with different additional property and should log expected output to console 1`] = ` +Array [ + "class Root { + private _email?: string; + private _extensions?: Map; + + constructor(input: { + email?: string, + extensions?: Map, + }) { + this._email = input.email; + this._extensions = input.extensions; + } + + get email(): string | undefined { return this._email; } + set email(email: string | undefined) { this._email = email; } + + get extensions(): Map | undefined { return this._extensions; } + set extensions(extensions: Map | undefined) { this._extensions = extensions; } +}", +] +`; diff --git a/examples/json-schema-additional-properties-representation/index.spec.ts b/examples/json-schema-additional-properties-representation/index.spec.ts new file mode 100644 index 0000000000..5bac9c599c --- /dev/null +++ b/examples/json-schema-additional-properties-representation/index.spec.ts @@ -0,0 +1,15 @@ +const spy = jest.spyOn(global.console, 'log').mockImplementation(() => { + return; +}); +import { generate } from './index'; + +describe('Should be able to render object with different additional property', () => { + afterAll(() => { + jest.restoreAllMocks(); + }); + test('and should log expected output to console', async () => { + await generate(); + expect(spy.mock.calls.length).toEqual(1); + expect(spy.mock.calls[0]).toMatchSnapshot(); + }); +}); diff --git a/examples/json-schema-additional-properties-representation/index.ts b/examples/json-schema-additional-properties-representation/index.ts new file mode 100644 index 0000000000..656de9c2a6 --- /dev/null +++ b/examples/json-schema-additional-properties-representation/index.ts @@ -0,0 +1,29 @@ +import { TypeScriptGenerator } from '../../src'; + +const generator = new TypeScriptGenerator({ + processorOptions: { + jsonSchema: { + propertyNameForAdditionalProperties: 'extensions' + } + } +}); +const jsonSchemaDraft7 = { + $schema: 'http://json-schema.org/draft-07/schema#', + type: 'object', + additionalProperties: true, + properties: { + email: { + type: 'string' + } + } +}; + +export async function generate(): Promise { + const models = await generator.generate(jsonSchemaDraft7); + for (const model of models) { + console.log(model.result); + } +} +if (require.main === module) { + generate(); +} diff --git a/examples/json-schema-additional-properties-representation/package-lock.json b/examples/json-schema-additional-properties-representation/package-lock.json new file mode 100644 index 0000000000..56ab4e873b --- /dev/null +++ b/examples/json-schema-additional-properties-representation/package-lock.json @@ -0,0 +1,10 @@ +{ + "name": "typescript-interface", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "hasInstallScript": true + } + } +} diff --git a/examples/json-schema-additional-properties-representation/package.json b/examples/json-schema-additional-properties-representation/package.json new file mode 100644 index 0000000000..409205d5da --- /dev/null +++ b/examples/json-schema-additional-properties-representation/package.json @@ -0,0 +1,10 @@ +{ + "config" : { "example_name" : "json-schema-additional-properties-representation" }, + "scripts": { + "install": "cd ../.. && npm i", + "start": "../../node_modules/.bin/ts-node --cwd ../../ ./examples/$npm_package_config_example_name/index.ts", + "start:windows": "..\\..\\node_modules\\.bin\\ts-node --cwd ..\\..\\ .\\examples\\%npm_package_config_example_name%\\index.ts", + "test": "../../node_modules/.bin/jest --config=../../jest.config.js ./examples/$npm_package_config_example_name/index.spec.ts", + "test:windows": "..\\..\\node_modules\\.bin\\jest --config=..\\..\\jest.config.js examples/%npm_package_config_example_name%/index.spec.ts" + } +} diff --git a/examples/json-schema-single-enum-as-const/__snapshots__/index.spec.ts.snap b/examples/json-schema-single-enum-as-const/__snapshots__/index.spec.ts.snap index 8957750ed2..eb69dbe1ec 100644 --- a/examples/json-schema-single-enum-as-const/__snapshots__/index.spec.ts.snap +++ b/examples/json-schema-single-enum-as-const/__snapshots__/index.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Should be able to render TEMPLATE and should log expected output to console 1`] = ` +exports[`Should be able to render enum with single value as const and should log expected output to console 1`] = ` Array [ "class Root { private _email?: 'test' = 'test'; diff --git a/examples/json-schema-single-enum-as-const/index.spec.ts b/examples/json-schema-single-enum-as-const/index.spec.ts index 4787d8879e..505a321c64 100644 --- a/examples/json-schema-single-enum-as-const/index.spec.ts +++ b/examples/json-schema-single-enum-as-const/index.spec.ts @@ -3,7 +3,7 @@ const spy = jest.spyOn(global.console, 'log').mockImplementation(() => { }); import { generate } from './index'; -describe('Should be able to render TEMPLATE', () => { +describe('Should be able to render enum with single value as const', () => { afterAll(() => { jest.restoreAllMocks(); }); diff --git a/src/helpers/CommonModelToMetaModel.ts b/src/helpers/CommonModelToMetaModel.ts index 3bd452242d..5da841bd68 100644 --- a/src/helpers/CommonModelToMetaModel.ts +++ b/src/helpers/CommonModelToMetaModel.ts @@ -582,7 +582,8 @@ export function convertToObjectModel( jsonSchemaModel.additionalProperties !== undefined || jsonSchemaModel.patternProperties !== undefined ) { - let propertyName = 'additionalProperties'; + let propertyName = + options.propertyNameForAdditionalProperties ?? 'additionalProperties'; while (metaModel.properties[String(propertyName)] !== undefined) { propertyName = `reserved_${propertyName}`; } diff --git a/src/processors/JsonSchemaInputProcessor.ts b/src/processors/JsonSchemaInputProcessor.ts index 46382be54c..6f1d8f5f60 100644 --- a/src/processors/JsonSchemaInputProcessor.ts +++ b/src/processors/JsonSchemaInputProcessor.ts @@ -23,6 +23,11 @@ export interface JsonSchemaProcessorOptions extends InterpreterOptions { * Use this option to reduce the number of enums being created and use constant values instead. */ interpretSingleEnumAsConst?: boolean; + + /** + * This option changes which property name that should be used to represent `additionalProperties` in JSON Schema + */ + propertyNameForAdditionalProperties?: string; } export const defaultJsonSchemaProcessorOptions: JsonSchemaProcessorOptions = { @@ -30,7 +35,8 @@ export const defaultJsonSchemaProcessorOptions: JsonSchemaProcessorOptions = { disableCache: false, ignoreAdditionalItems: false, ignoreAdditionalProperties: false, - interpretSingleEnumAsConst: false + interpretSingleEnumAsConst: false, + propertyNameForAdditionalProperties: 'additionalProperties' }; /**