From a5eb0b7a8478d661da7058ccd848e4466fb34f28 Mon Sep 17 00:00:00 2001 From: Michael Schroder Date: Thu, 26 Mar 2026 04:49:42 -0700 Subject: [PATCH 1/8] Initial support for x-enum-varnames in openapi3 emitter --- .../cli/actions/convert/generators/generate-model.ts | 9 ++++++++- packages/openapi3/src/openapi.ts | 11 +++++++++++ packages/openapi3/src/schema-emitter-3-1.ts | 3 +++ packages/openapi3/src/types.ts | 4 ++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/openapi3/src/cli/actions/convert/generators/generate-model.ts b/packages/openapi3/src/cli/actions/convert/generators/generate-model.ts index f73040d194b..04821f37b11 100644 --- a/packages/openapi3/src/cli/actions/convert/generators/generate-model.ts +++ b/packages/openapi3/src/cli/actions/convert/generators/generate-model.ts @@ -58,7 +58,14 @@ function generateEnum(tsEnum: TypeSpecEnum): string { const schema = tsEnum.schema; - if (schema.enum) { + if (schema.enum && schema["x-enum-varnames"]) { + definitions.push( + ...schema.enum.map( + (e, i) => + `${schema["x-enum-varnames"] && schema["x-enum-varnames"][i] ? schema["x-enum-varnames"][i] : JSON.stringify(e)}: ${JSON.stringify(e)},`, + ), + ); + } else if (schema.enum) { definitions.push(...schema.enum.map((e) => `${JSON.stringify(e)},`)); } diff --git a/packages/openapi3/src/openapi.ts b/packages/openapi3/src/openapi.ts index a4559806325..69df76d927f 100644 --- a/packages/openapi3/src/openapi.ts +++ b/packages/openapi3/src/openapi.ts @@ -1645,6 +1645,17 @@ function createOAPIEmitter( ) { schema.enum = [...new Set([...schema.enum, ...apply.schema.enum])]; } + if ( + "x-enum-varnames" in schema && + schema["x-enum-varnames"] && + apply.schema && + "x-enum-varnames" in apply.schema && + apply.schema["x-enum-varnames"] + ) { + schema["x-enum-varnames"] = [ + ...new Set([...schema["x-enum-varnames"], ...apply.schema["x-enum-varnames"]]), + ]; + } target.schema = schema; } else { Object.assign(target, apply); diff --git a/packages/openapi3/src/schema-emitter-3-1.ts b/packages/openapi3/src/schema-emitter-3-1.ts index 42b07d00c28..4197d190a7e 100644 --- a/packages/openapi3/src/schema-emitter-3-1.ts +++ b/packages/openapi3/src/schema-emitter-3-1.ts @@ -185,9 +185,11 @@ export class OpenAPI31SchemaEmitter extends OpenAPI3SchemaEmitterBase(); const enumValues = new Set(); + const enumKeyNames = new Set(); for (const member of en.members.values()) { enumTypes.add(typeof member.value === "number" ? "number" : "string"); enumValues.add(member.value ?? member.name); + enumKeyNames.add(member.name ?? null); } const enumTypesArray = [...enumTypes]; @@ -195,6 +197,7 @@ export class OpenAPI31SchemaEmitter extends OpenAPI3SchemaEmitterBase = AdditionalVocab */ enum?: (string | number | boolean | null)[]; + "x-enum-varnames"?: (string | null)[]; + /** * Functionally equivalent to "enum" with a single value. * An instance validates successfully if its value is equal to the value of this keyword. From 811bc04ea3ec2c3750fb46a39989393e0fde32f0 Mon Sep 17 00:00:00 2001 From: Michael Schroder Date: Thu, 26 Mar 2026 08:53:12 -0700 Subject: [PATCH 2/8] Cleaned up code and made more idiomatic --- packages/http-server-js/src/util/openapi3.ts | 1 + packages/openapi3/README.md | 8 ++++++++ packages/openapi3/src/lib.ts | 15 +++++++++++++++ packages/openapi3/src/openapi.ts | 3 +++ packages/openapi3/src/schema-emitter-3-0.ts | 12 +++++++++++- packages/openapi3/src/schema-emitter-3-1.ts | 11 +++++++++-- packages/openapi3/src/types.ts | 4 ---- .../docs/emitters/openapi3/reference/emitter.md | 8 ++++++++ 8 files changed, 55 insertions(+), 7 deletions(-) diff --git a/packages/http-server-js/src/util/openapi3.ts b/packages/http-server-js/src/util/openapi3.ts index 268ec62fb17..c0f68551e25 100644 --- a/packages/http-server-js/src/util/openapi3.ts +++ b/packages/http-server-js/src/util/openapi3.ts @@ -26,6 +26,7 @@ export async function getOpenApi3ServiceRecord( const serviceRecords = await openapi3.getOpenAPI3(program, { "include-x-typespec-name": "never", + "include-x-enum-varnames": false, "omit-unreachable-types": true, "safeint-strategy": "int64", }); diff --git a/packages/openapi3/README.md b/packages/openapi3/README.md index 6512a4c1a86..480393d4ef8 100644 --- a/packages/openapi3/README.md +++ b/packages/openapi3/README.md @@ -108,6 +108,14 @@ By default all types declared under the service namespace will be included. With If the generated openapi types should have the `x-typespec-name` extension set with the name of the TypeSpec type that created it. This extension is meant for debugging and should not be depended on. +### `include-x-enum-varnames` + +**Type:** `boolean` + +If the generated openapi types should have the `x-enum-varnames` extension filled for enum types. +This maintains the key of any enum value the defines it in the form `key: value`. +The default behavior is to use the value as both the key and value. + ### `safeint-strategy` **Type:** `"double-int" | "int64"` diff --git a/packages/openapi3/src/lib.ts b/packages/openapi3/src/lib.ts index d5c29f3179b..5350a9d9044 100644 --- a/packages/openapi3/src/lib.ts +++ b/packages/openapi3/src/lib.ts @@ -68,6 +68,14 @@ export interface OpenAPI3EmitterOptions { */ "include-x-typespec-name"?: "inline-only" | "never"; + /** + * If the generated openapi types should have the `x-enum-varnames` extension filled for enum types. + * This maintains the key of any enum value the defines it in the form `key: value`. + * The default behavior is to use the value as both the key and value. + * @default false + */ + "include-x-enum-varnames"?: boolean; + /** * How to handle safeint type. Options are: * - `double-int`: Will produce `type: integer, format: double-int` @@ -217,6 +225,13 @@ const EmitterOptionsSchema: JSONSchemaType = { description: "If the generated openapi types should have the `x-typespec-name` extension set with the name of the TypeSpec type that created it.\nThis extension is meant for debugging and should not be depended on.", }, + "include-x-enum-varnames": { + type: "boolean", + nullable: true, + default: false, + description: + "If the generated openapi types should have the `x-enum-varnames` extension filled for enum types.\nThis maintains the key of any enum value the defines it in the form `key: value`.\nThe default behavior is to use the value as both the key and value.", + }, "safeint-strategy": { type: "string", enum: ["double-int", "int64"], diff --git a/packages/openapi3/src/openapi.ts b/packages/openapi3/src/openapi.ts index 69df76d927f..e8616b14c9e 100644 --- a/packages/openapi3/src/openapi.ts +++ b/packages/openapi3/src/openapi.ts @@ -139,6 +139,7 @@ const defaultOptions = { "new-line": "lf", "omit-unreachable-types": false, "include-x-typespec-name": "never", + "include-x-enum-varnames": false, "safeint-strategy": "int64", "seal-object-schemas": false, } as const; @@ -225,6 +226,7 @@ export function resolveOptions( newLine: resolvedOptions["new-line"], omitUnreachableTypes: resolvedOptions["omit-unreachable-types"], includeXTypeSpecName: resolvedOptions["include-x-typespec-name"], + includeXEnumVarNames: resolvedOptions["include-x-enum-varnames"], safeintStrategy: resolvedOptions["safeint-strategy"], outputFile: resolvePath(context.emitterOutputDir, specDir, outputFile), openapiVersions, @@ -268,6 +270,7 @@ export interface ResolvedOpenAPI3EmitterOptions { newLine: NewLine; omitUnreachableTypes: boolean; includeXTypeSpecName: "inline-only" | "never"; + includeXEnumVarNames: boolean; safeintStrategy: "double-int" | "int64"; sealObjectSchemas: boolean; parameterExamplesStrategy?: "data" | "serialized"; diff --git a/packages/openapi3/src/schema-emitter-3-0.ts b/packages/openapi3/src/schema-emitter-3-0.ts index da93ac944f6..c51948f946e 100644 --- a/packages/openapi3/src/schema-emitter-3-0.ts +++ b/packages/openapi3/src/schema-emitter-3-0.ts @@ -121,20 +121,30 @@ export class OpenAPI3SchemaEmitter extends OpenAPI3SchemaEmitterBase(); const enumValues = new Set(); + const enumKeyNames = new Set(); for (const member of en.members.values()) { enumTypes.add(typeof member.value === "number" ? "number" : "string"); enumValues.add(member.value ?? member.name); + enumKeyNames.add(member.name ?? null); } if (enumTypes.size > 1) { reportDiagnostic(program, { code: "enum-unique-type", target: en }); } - const schema: OpenAPI3Schema = { + let schema: OpenAPI3Schema = { type: enumTypes.values().next().value!, enum: [...enumValues], }; + if (this._options.includeXEnumVarNames) { + schema = { + type: schema.type, + enum: schema.enum, + "x-enum-varnames": [...enumKeyNames], + }; + } + return this.applyConstraints(en, schema); } diff --git a/packages/openapi3/src/schema-emitter-3-1.ts b/packages/openapi3/src/schema-emitter-3-1.ts index 4197d190a7e..14a83265488 100644 --- a/packages/openapi3/src/schema-emitter-3-1.ts +++ b/packages/openapi3/src/schema-emitter-3-1.ts @@ -194,12 +194,19 @@ export class OpenAPI31SchemaEmitter extends OpenAPI3SchemaEmitterBase = AdditionalVocab */ enum?: (string | number | boolean | null)[]; - "x-enum-varnames"?: (string | null)[]; - /** * Functionally equivalent to "enum" with a single value. * An instance validates successfully if its value is equal to the value of this keyword. diff --git a/website/src/content/docs/docs/emitters/openapi3/reference/emitter.md b/website/src/content/docs/docs/emitters/openapi3/reference/emitter.md index a15c4c7e603..551ba541d19 100644 --- a/website/src/content/docs/docs/emitters/openapi3/reference/emitter.md +++ b/website/src/content/docs/docs/emitters/openapi3/reference/emitter.md @@ -102,6 +102,14 @@ By default all types declared under the service namespace will be included. With If the generated openapi types should have the `x-typespec-name` extension set with the name of the TypeSpec type that created it. This extension is meant for debugging and should not be depended on. +### `include-x-enum-varnames` + +**Type:** `boolean` + +If the generated openapi types should have the `x-enum-varnames` extension filled for enum types. +This maintains the key of any enum value the defines it in the form `key: value`. +The default behavior is to use the value as both the key and value. + ### `safeint-strategy` **Type:** `"double-int" | "int64"` From 30da2962ed12111c89c3bb4a63ace698537850a2 Mon Sep 17 00:00:00 2001 From: Michael Schroder Date: Thu, 26 Mar 2026 08:58:21 -0700 Subject: [PATCH 3/8] Fixed documentation wording --- packages/openapi3/README.md | 4 ++-- packages/openapi3/src/lib.ts | 6 +++--- .../docs/docs/emitters/openapi3/reference/emitter.md | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/openapi3/README.md b/packages/openapi3/README.md index 480393d4ef8..fd4ccacbc52 100644 --- a/packages/openapi3/README.md +++ b/packages/openapi3/README.md @@ -112,8 +112,8 @@ This extension is meant for debugging and should not be depended on. **Type:** `boolean` -If the generated openapi types should have the `x-enum-varnames` extension filled for enum types. -This maintains the key of any enum value the defines it in the form `key: value`. +If the generated openapi enums should have the `x-enum-varnames` extension filled. +This maintains the key of any enum value that defines it in the form `key: value`. The default behavior is to use the value as both the key and value. ### `safeint-strategy` diff --git a/packages/openapi3/src/lib.ts b/packages/openapi3/src/lib.ts index 5350a9d9044..61b501e8558 100644 --- a/packages/openapi3/src/lib.ts +++ b/packages/openapi3/src/lib.ts @@ -69,8 +69,8 @@ export interface OpenAPI3EmitterOptions { "include-x-typespec-name"?: "inline-only" | "never"; /** - * If the generated openapi types should have the `x-enum-varnames` extension filled for enum types. - * This maintains the key of any enum value the defines it in the form `key: value`. + * If the generated openapi enums should have the `x-enum-varnames` extension filled. + * This maintains the key of any enum value that defines it in the form `key: value`. * The default behavior is to use the value as both the key and value. * @default false */ @@ -230,7 +230,7 @@ const EmitterOptionsSchema: JSONSchemaType = { nullable: true, default: false, description: - "If the generated openapi types should have the `x-enum-varnames` extension filled for enum types.\nThis maintains the key of any enum value the defines it in the form `key: value`.\nThe default behavior is to use the value as both the key and value.", + "If the generated openapi enums should have the `x-enum-varnames` extension filled.\nThis maintains the key of any enum value that defines it in the form `key: value`.\nThe default behavior is to use the value as both the key and value.", }, "safeint-strategy": { type: "string", diff --git a/website/src/content/docs/docs/emitters/openapi3/reference/emitter.md b/website/src/content/docs/docs/emitters/openapi3/reference/emitter.md index 551ba541d19..9c4cca10da2 100644 --- a/website/src/content/docs/docs/emitters/openapi3/reference/emitter.md +++ b/website/src/content/docs/docs/emitters/openapi3/reference/emitter.md @@ -106,8 +106,8 @@ This extension is meant for debugging and should not be depended on. **Type:** `boolean` -If the generated openapi types should have the `x-enum-varnames` extension filled for enum types. -This maintains the key of any enum value the defines it in the form `key: value`. +If the generated openapi enums should have the `x-enum-varnames` extension filled. +This maintains the key of any enum value that defines it in the form `key: value`. The default behavior is to use the value as both the key and value. ### `safeint-strategy` From 6df483aaa637314ac6ada9e775935e2ba3a37c77 Mon Sep 17 00:00:00 2001 From: Michael Schroder Date: Thu, 26 Mar 2026 09:22:50 -0700 Subject: [PATCH 4/8] Changed enum member intermediate data structure from Set to Map --- .../actions/convert/generators/generate-model.ts | 3 +-- packages/openapi3/src/schema-emitter-3-0.ts | 16 +++++----------- packages/openapi3/src/schema-emitter-3-1.ts | 16 +++++----------- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/packages/openapi3/src/cli/actions/convert/generators/generate-model.ts b/packages/openapi3/src/cli/actions/convert/generators/generate-model.ts index 04821f37b11..811766c4c75 100644 --- a/packages/openapi3/src/cli/actions/convert/generators/generate-model.ts +++ b/packages/openapi3/src/cli/actions/convert/generators/generate-model.ts @@ -61,8 +61,7 @@ function generateEnum(tsEnum: TypeSpecEnum): string { if (schema.enum && schema["x-enum-varnames"]) { definitions.push( ...schema.enum.map( - (e, i) => - `${schema["x-enum-varnames"] && schema["x-enum-varnames"][i] ? schema["x-enum-varnames"][i] : JSON.stringify(e)}: ${JSON.stringify(e)},`, + (e, i) => `${schema["x-enum-varnames"][i] ?? JSON.stringify(e)}: ${JSON.stringify(e)},`, ), ); } else if (schema.enum) { diff --git a/packages/openapi3/src/schema-emitter-3-0.ts b/packages/openapi3/src/schema-emitter-3-0.ts index c51948f946e..43161861c1f 100644 --- a/packages/openapi3/src/schema-emitter-3-0.ts +++ b/packages/openapi3/src/schema-emitter-3-0.ts @@ -120,29 +120,23 @@ export class OpenAPI3SchemaEmitter extends OpenAPI3SchemaEmitterBase(); - const enumValues = new Set(); - const enumKeyNames = new Set(); + const enumMembers = new Map(); for (const member of en.members.values()) { enumTypes.add(typeof member.value === "number" ? "number" : "string"); - enumValues.add(member.value ?? member.name); - enumKeyNames.add(member.name ?? null); + enumMembers.set(member.value ?? member.name, member.name); } if (enumTypes.size > 1) { reportDiagnostic(program, { code: "enum-unique-type", target: en }); } - let schema: OpenAPI3Schema = { + const schema: OpenAPI3Schema = { type: enumTypes.values().next().value!, - enum: [...enumValues], + enum: [...enumMembers.keys()], }; if (this._options.includeXEnumVarNames) { - schema = { - type: schema.type, - enum: schema.enum, - "x-enum-varnames": [...enumKeyNames], - }; + schema["x-enum-varnames"] = [...enumMembers.values()]; } return this.applyConstraints(en, schema); diff --git a/packages/openapi3/src/schema-emitter-3-1.ts b/packages/openapi3/src/schema-emitter-3-1.ts index 14a83265488..c121398bfec 100644 --- a/packages/openapi3/src/schema-emitter-3-1.ts +++ b/packages/openapi3/src/schema-emitter-3-1.ts @@ -184,27 +184,21 @@ export class OpenAPI31SchemaEmitter extends OpenAPI3SchemaEmitterBase(); - const enumValues = new Set(); - const enumKeyNames = new Set(); + const enumMembers = new Map(); for (const member of en.members.values()) { enumTypes.add(typeof member.value === "number" ? "number" : "string"); - enumValues.add(member.value ?? member.name); - enumKeyNames.add(member.name ?? null); + enumMembers.set(member.value ?? member.name, member.name); } const enumTypesArray = [...enumTypes]; - let schema: OpenAPISchema3_1 = { + const schema: OpenAPISchema3_1 = { type: enumTypesArray.length === 1 ? enumTypesArray[0] : enumTypesArray, - enum: [...enumValues], + enum: [...enumMembers.keys()], }; if (this._options.includeXEnumVarNames) { - schema = { - type: schema.type, - enum: schema.enum, - "x-enum-varnames": [...enumKeyNames], - }; + schema["x-enum-varnames"] = [...enumMembers.values()]; } return this.applyConstraints(en, schema); From d46df2128515bfc9b9aabfa322219d28353a36c5 Mon Sep 17 00:00:00 2001 From: Michael Schroder Date: Thu, 26 Mar 2026 09:51:33 -0700 Subject: [PATCH 5/8] Use map for enum merging --- packages/openapi3/src/openapi.ts | 40 ++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/packages/openapi3/src/openapi.ts b/packages/openapi3/src/openapi.ts index e8616b14c9e..42039163ad1 100644 --- a/packages/openapi3/src/openapi.ts +++ b/packages/openapi3/src/openapi.ts @@ -1646,18 +1646,34 @@ function createOAPIEmitter( "enum" in apply.schema && apply.schema.enum ) { - schema.enum = [...new Set([...schema.enum, ...apply.schema.enum])]; - } - if ( - "x-enum-varnames" in schema && - schema["x-enum-varnames"] && - apply.schema && - "x-enum-varnames" in apply.schema && - apply.schema["x-enum-varnames"] - ) { - schema["x-enum-varnames"] = [ - ...new Set([...schema["x-enum-varnames"], ...apply.schema["x-enum-varnames"]]), - ]; + const hasEnumVarnames = + "x-enum-varnames" in schema && + schema["x-enum-varnames"] && + "x-enum-varnames" in apply.schema && + apply.schema["x-enum-varnames"]; + + // Merge enum values and varnames together via a map so that + // deduplication by enum value keeps the two arrays index-aligned. + const mergedEnumMembers = new Map(); + for (let i = 0; i < schema.enum.length; i++) { + mergedEnumMembers.set( + schema.enum[i], + hasEnumVarnames ? schema["x-enum-varnames"]![i] : undefined, + ); + } + for (let i = 0; i < apply.schema.enum.length; i++) { + if (!mergedEnumMembers.has(apply.schema.enum[i])) { + mergedEnumMembers.set( + apply.schema.enum[i], + hasEnumVarnames ? apply.schema["x-enum-varnames"]![i] : undefined, + ); + } + } + + schema.enum = [...mergedEnumMembers.keys()]; + if (hasEnumVarnames) { + schema["x-enum-varnames"] = [...mergedEnumMembers.values()] as string[]; + } } target.schema = schema; } else { From 237f96cbe95b107a7b45baaadbb0433df6b3bc03 Mon Sep 17 00:00:00 2001 From: Michael Schroder Date: Thu, 26 Mar 2026 09:52:03 -0700 Subject: [PATCH 6/8] Added changelog entry for x-enum-varnames --- .chronus/changes/openapi3-x-enum-varnames-2026-3-26.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/openapi3-x-enum-varnames-2026-3-26.md diff --git a/.chronus/changes/openapi3-x-enum-varnames-2026-3-26.md b/.chronus/changes/openapi3-x-enum-varnames-2026-3-26.md new file mode 100644 index 00000000000..98d5869e649 --- /dev/null +++ b/.chronus/changes/openapi3-x-enum-varnames-2026-3-26.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@typespec/openapi3" +--- + +Add `include-x-enum-varnames` emitter option to emit the `x-enum-varnames` OpenAPI extension on enums, preserving the original enum member names as defined in TypeSpec From 72c0425d1488b4701e96c2061edcb22ac09d73a5 Mon Sep 17 00:00:00 2001 From: Michael Schroder Date: Thu, 26 Mar 2026 10:16:44 -0700 Subject: [PATCH 7/8] Added tests --- packages/openapi3/test/openapi-output.test.ts | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/packages/openapi3/test/openapi-output.test.ts b/packages/openapi3/test/openapi-output.test.ts index 650e5cb86bf..b4d32176cea 100644 --- a/packages/openapi3/test/openapi-output.test.ts +++ b/packages/openapi3/test/openapi-output.test.ts @@ -66,6 +66,51 @@ worksFor(supportedVersions, ({ oapiForModel, openApiFor, openapiWithOptions }) = }); }); + describe("openapi3: x-enum-varnames", () => { + it("doesn't include x-enum-varnames by default", async () => { + const output = await openapiWithOptions( + ` + enum Foo { A: "a", B: "b" } + `, + {}, + ); + ok(!("x-enum-varnames" in output.components!.schemas!.Foo)); + }); + + it(`doesn't include x-enum-varnames when option is false`, async () => { + const output = await openapiWithOptions( + ` + enum Foo { A: "a", B: "b" } + `, + { "include-x-enum-varnames": false }, + ); + ok(!("x-enum-varnames" in output.components!.schemas!.Foo)); + }); + + it(`includes x-enum-varnames when option is true`, async () => { + const output = await openapiWithOptions( + ` + enum Foo { A: "a", B: "b" } + `, + { "include-x-enum-varnames": true }, + ); + const schema: any = output.components!.schemas!.Foo; + deepStrictEqual(schema["x-enum-varnames"], ["A", "B"]); + }); + + it(`x-enum-varnames stays aligned with enum values when members share values`, async () => { + const output = await openapiWithOptions( + ` + enum Foo { A: "a", B: "b", AlsoA: "a" } + `, + { "include-x-enum-varnames": true }, + ); + const schema: any = output.components!.schemas!.Foo; + deepStrictEqual(schema.enum, ["a", "b"]); + deepStrictEqual(schema["x-enum-varnames"], ["AlsoA", "B"]); + }); + }); + describe("openapi3: literals", () => { const cases = [ ["1", { type: "number", enum: [1] }], From 6391ffb76104533a7f541e6f327bb5d06a742d4e Mon Sep 17 00:00:00 2001 From: Michael Schroder Date: Thu, 26 Mar 2026 10:38:42 -0700 Subject: [PATCH 8/8] Added default value to readme --- packages/openapi3/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/openapi3/README.md b/packages/openapi3/README.md index fd4ccacbc52..7b412a6c7f3 100644 --- a/packages/openapi3/README.md +++ b/packages/openapi3/README.md @@ -116,6 +116,8 @@ If the generated openapi enums should have the `x-enum-varnames` extension fille This maintains the key of any enum value that defines it in the form `key: value`. The default behavior is to use the value as both the key and value. +Default: `false` + ### `safeint-strategy` **Type:** `"double-int" | "int64"`