diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index d3a0e4feef..30678943dc 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -306,7 +306,7 @@ export class Ref { public get definitionName(): string | undefined { const pe = arrayGetFromEnd(this.path, 2); if (pe === undefined) return undefined; - if (keyOrIndex(pe) === "definitions") + if (keyOrIndex(pe) === "definitions" || keyOrIndex(pe) === "$defs") return keyOrIndex(defined(arrayLast(this.path))); return undefined; } diff --git a/test/inputs/schema/light.1.json b/test/inputs/schema/light.1.json new file mode 100644 index 0000000000..478f25fe74 --- /dev/null +++ b/test/inputs/schema/light.1.json @@ -0,0 +1,7 @@ +{ + "LightParams": { + "outlet_id": "outlet-1", + "app_id": "app-1", + "rgba": "255,255,255,1" + } +} diff --git a/test/inputs/schema/light.schema b/test/inputs/schema/light.schema new file mode 100644 index 0000000000..42c4b43b64 --- /dev/null +++ b/test/inputs/schema/light.schema @@ -0,0 +1,21 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$defs": { + "LightParams": { + "type": "object", + "properties": { + "outlet_id": { "type": "string" }, + "app_id": { "type": "string" }, + "rgba": { "type": "string" } + }, + "additionalProperties": false, + "required": ["outlet_id", "app_id", "rgba"] + } + }, + "type": "object", + "properties": { + "LightParams": { "$ref": "#/$defs/LightParams" } + }, + "additionalProperties": false, + "required": ["LightParams"] +} diff --git a/test/unit/json-schema-definitions.test.ts b/test/unit/json-schema-definitions.test.ts new file mode 100644 index 0000000000..f63702d495 --- /dev/null +++ b/test/unit/json-schema-definitions.test.ts @@ -0,0 +1,51 @@ +import { + FetchingJSONSchemaStore, + InputData, + JSONSchemaInput, + quicktype, +} from "quicktype-core"; +import { expect, test } from "vitest"; + +const lightSchema = { + $schema: "https://json-schema.org/draft/2020-12/schema", + $defs: { + LightParams: { + type: "object", + properties: { + outlet_id: { type: "string" }, + app_id: { type: "string" }, + rgba: { type: "string" }, + }, + additionalProperties: false, + required: ["outlet_id", "app_id", "rgba"], + }, + }, + type: "object", + properties: { + LightParams: { $ref: "#/$defs/LightParams" }, + }, + additionalProperties: false, + required: ["LightParams"], +}; + +test("a type under $defs keeps its definition name (issue #2778)", async () => { + const schemaInput = new JSONSchemaInput(new FetchingJSONSchemaStore()); + await schemaInput.addSource({ + name: "LightSchema", + schema: JSON.stringify(lightSchema), + }); + const inputData = new InputData(); + inputData.addInput(schemaInput); + + const result = await quicktype({ + inputData, + lang: "typescript", + rendererOptions: { "just-types": "true" }, + }); + const output = result.lines.join("\n"); + + // The fixture exercises this schema end-to-end, but generated symbol names + // are not observable at runtime, so assert the regression here. + expect(output).toContain("LightParams: LightParams;"); + expect(output).toContain("export interface LightParams {"); +});