TypeSpec JSON Schema Emitter 使用指南:调用方式与全部 Emitter 配置项详解
2026/9/19 10:37:50 网站建设 项目流程

TypeSpec JSON Schema Emitter 使用指南:调用方式与全部 Emitter 配置项详解

【免费下载链接】typespec项目地址: https://gitcode.com/GitHub_Trending/ty/typespec

本指南完整讲解@typespec/json-schemaEmitter 的两种调用方式(命令行与tspconfig.yaml配置)以及全部 8 个 Emitter 选项的语义、默认值与使用场景,并结合本仓库源码说明每个选项在底层是如何生效的。读完本文,你将能独立完成「TypeSpec 模型 → JSON Schema(JSON/YAML)」的编译配置,并针对 64 位整数、多态模型、Schema 打包等常见场景做出正确的选项决策。

准备工作:安装与最小示例

@typespec/json-schema是 TypeSpec 官方的 JSON Schema 生成器,其包描述位于 packages/json-schema/package.json,安装方式:

npm install @typespec/json-schema

生成 Schema 前,需要先用@jsonSchema装饰器标记要输出的声明。装饰器定义在 packages/json-schema/lib/main.tsp:加在命名空间上会输出该命名空间内的所有模型,加在某个声明上则只输出该声明(可选参数baseUri/id)。一个最小可编译示例:

import "@typespec/json-schema"; using JsonSchema; @jsonSchema namespace Example; model Car { make: string; modelName: string; }

一、两种调用方式

1. 命令行方式

在包含main.tsp的目录下执行:

tsp compile . --emit=@typespec/json-schema

tsp compile会读取当前目录的 TypeSpec 入口文件,编译后仅调用@typespec/json-schema这一个 Emitter。命令行的优势是适合快速验证,无需维护配置文件。

2. 配置文件方式

tspconfig.yaml中声明启用该 Emitter:

emit: - "@typespec/json-schema"

此时执行不带--emittsp compile .即可生效。配置文件方式便于把 Emitter 及选项固化到项目中,团队共享同一套输出行为。

3. 在配置中扩展选项

emit下列出启用的 Emitter,options下以 Emitter 包名为键、以键值对形式给出该 Emitter 的选项:

emit: - "@typespec/json-schema" options: "@typespec/json-schema": option: value

option: value替换为下文任一实际选项即可,例如file-type: json

二、Emitter 选项总览

所有选项均定义在 packages/json-schema/src/lib.ts 的JSONSchemaEmitterOptions接口与EmitterOptionsSchema中,编译时会据此做类型校验(additionalProperties: false,即未知选项会被拒绝)。汇总如下:

选项类型默认值作用
emitter-output-dirabsolutePath{output-dir}/@typespec/json-schema输出目录
file-type"yaml" \| "json"由输出文件扩展名推断序列化格式
int64-strategy"string" \| "number"未显式指定时按"string"处理64 位整数在 Schema 中的表示
bundleIdstring将全部 Schema 打包进单个文档
emitAllModelsbooleanfalse忽略@jsonSchema,输出所有模型
emitAllRefsbooleanfalse输出所有被引用类型的 Schema
seal-object-schemasbooleanfalse默认封闭对象 Schema
polymorphic-models-strategy"ignore" \| "oneOf" \| "anyOf""ignore"@discriminator模型的多态输出策略

下面逐项展开。

三、逐项详解

emitter-output-dir

类型:absolutePath

作用:指定 Emitter 的输出目录。默认值为{output-dir}/@typespec/json-schema,即编译器输出目录下的@typespec/json-schema子目录;output-dir本身由编译器的输出目录配置决定(可在tspconfig.yaml顶层通过output-dir设置)。显式配置示例:

options: "@typespec/json-schema": emitter-output-dir: "./schemas"

从源码看,输出目录同时决定了 Schema 默认$id的生成基准:json-schema-emitter.ts 中#getDeclId会取emitterOutputDir与当前源文件路径的相对关系来构造$id,因此调整输出目录会直接反映到生成的 Schema ID 上。

file-type

类型:"yaml" | "json"

作用:选择 Schema 的序列化格式。设置为json时输出.json文件,否则输出.yaml文件。序列化逻辑位于 json-schema-emitter.ts 的#serializeSourceFileContent:JSON 使用 4 空格缩进的JSON.stringify;YAML 使用yaml库序列化,并显式关闭aliasDuplicateObjects、设置lineWidth: 0避免长行被折行。文件扩展名同样由该选项决定(#fileExtension,见同文件 L1181-L1183)。

options: "@typespec/json-schema": file-type: json

int64-strategy

类型:"string" | "number"

作用:决定 64 位整数在「线上传输」时的表示方式:

  • string:序列化为字符串。JavaScript 的number无法精确表示全部 int64/uint64 取值范围,字符串形式跨语言互操作性最好,是推荐选择;
  • number:序列化为数字。直观但可能丢失精度,互操作性差。

底层实现在 json-schema-emitter.ts 的#getSchemaForStdScalarsint64/uint64string策略下输出{ type: "string" };在number策略下输出{ type: "integer" }——代码注释明确说明,之所以不附带minimum/maximum,是因为这些边界值无法在不损失精度的情况下写成字面量。注意:int8~int32uint8~uint32等小整数始终输出为带精确minimum/maximuminteger,不受此选项影响。

options: "@typespec/json-schema": int64-strategy: string

bundleId

类型:string

作用:提供bundleId后,所有应输出的 Schema 不再各自生成文件,而是被打包进单个JSON Schema 文档,各 Schema 挂到根文档的$defs下;bundleId同时作为根文档的$id和输出文件名。

打包实现在 json-schema-emitter.ts 的writeOutput:遍历所有shouldEmit的源文件,构造{ $schema, $id: bundleId, $defs }结构,再写入{emitterOutputDir}/{bundleId}。被引用但自身不作为根 Schema 输出的类型,也会通过bundledRefs机制递归并入$defs(见 L1041-L1058),避免引用悬空。相关打包测试可参考 packages/json-schema/test/bundling.test.ts。

options: "@typespec/json-schema": bundleId: schemas.json

emitAllModels

类型:boolean

作用:true时,所有模型声明都会输出为 JSON Schema,无需再逐个添加@jsonSchema装饰器。适合「整个规范全部转 Schema」的场景。

该选项在 Emitter 入口处直接改变遍历策略:packages/json-schema/src/on-emit.ts 的$onEmit中,当emitAllModels为真时调用emitter.emitProgram({ emitTypeSpecNamespace: false })走全程序发射路径;否则仅对getJsonSchemaTypes()(从 decorators.ts 收集的、被@jsonSchema标记的命名空间/声明)逐个emitType。同时,#shouldEmitRootSchema(json-schema-emitter.ts)也会把emitAllModels作为判定「是否作为根 Schema 输出」的条件之一。

options: "@typespec/json-schema": emitAllModels: true

emitAllRefs

类型:boolean

作用:true时,所有被引用的类型都会作为独立 JSON Schema 文件输出,即使该类型没有@jsonSchema装饰器、也不处于带@jsonSchema的命名空间内。即把引用链上的每一个类型都「提升」为可独立寻址的 Schema 文档。

emitAllModels相同,它也会在#shouldEmitRootSchema中参与根 Schema 判定(json-schema-emitter.ts)。区别在于:emitAllModels关注「声明本身是否输出」,emitAllRefs关注「被引用者是否也输出」。

seal-object-schemas

类型:boolean默认值:false

作用:true时,以对象 Schema 输出的模型若未显式指定,会默认加上unevaluatedProperties: { not: {} },即「除声明属性外不允许额外属性」,实现 Schema 封闭。

实现位于 json-schema-emitter.ts 的#applyModelIndexer:如果模型有 indexer(如Record<...>),会优先把 indexer 值类型发射为unevaluatedProperties;否则在seal-object-schemas开启且模型没有派生模型时,才写入{ not: {} }——注意「有派生模型时不封闭」这一细节,避免封闭后破坏继承体系。对象字面量(modelLiteral)同样会应用该逻辑。

options: "@typespec/json-schema": seal-object-schemas: true

polymorphic-models-strategy

类型:"ignore" | "oneOf" | "anyOf"默认值:"ignore"

作用:决定带@discriminator装饰器(多态基类)的模型如何发射:

  • ignore(默认):作为普通对象 Schema 发射;派生模型通过allOf引用基类,继承关系由allOf表达;
  • oneOf:发射一个oneOf联合,引用所有派生模型(闭合联合);
  • anyOf:发射一个anyOf联合,引用所有派生模型(开放联合)。

关键行为:使用oneOfanyOf时,派生模型会把基类的全部属性内联(而非allOf引用),从而避免「基类通过 oneOf/anyOf 引用派生类、派生类又通过 allOf 引用基类」造成的循环引用。相关实现见 json-schema-emitter.ts(modelDeclaration中的策略分支与#isBaseUsingDiscriminatedUnion)以及 L805-L953(#createDiscriminatedUnionDeclaration、属性内联#getAllModelProperties/#getAllRequiredModelProperties)。另外,若判别属性类型包含string(开放判别器),发射器还会自动追加一个「兜底变体」匹配未知判别值(见#isOpenDiscriminator#createCatchAllVariant)。相关测试可参考 packages/json-schema/test/discriminator.test.ts。

options: "@typespec/json-schema": polymorphic-models-strategy: oneOf

四、与装饰器生态的配合

Emitter 选项解决「怎么输出」,而「输出什么」由装饰器决定。除@jsonSchema外,lib/main.tsp 还提供@baseUri@id(控制 Schema ID)、@oneOf(联合强制用oneOf)、@multipleOf@contains/@minContains/@maxContains@uniqueItems@minProperties/@maxProperties@contentEncoding/@contentMediaType/@contentSchema@prefixItems@extension(注入自定义关键字)等,约束由 json-schema-emitter.ts 的#applyConstraints统一映射为 JSON Schema 关键字(如minLengthpatternformatdeprecated等),文档、示例与标准标量类型(int8~int64decimalplainDateutcDateTimebytes等)的 Schema 映射也都在该文件中,可作为深入阅读的入口。

五、常见组合示例

一个覆盖多种选项的完整tspconfig.yaml

emit: - "@typespec/json-schema" options: "@typespec/json-schema": file-type: json int64-strategy: string seal-object-schemas: true polymorphic-models-strategy: oneOf bundleId: bundle.json

六、小结

  • tsp compile . --emit=@typespec/json-schematspconfig.yamlemit即可启用;选项统一写在options["@typespec/json-schema"]下。
  • 8 个选项各司其职:file-type/emitter-output-dir控制输出形态;int64-strategy处理大整数精度;bundleId/emitAllModels/emitAllRefs控制发射范围与打包方式;seal-object-schemas控制 Schema 封闭性;polymorphic-models-strategy控制多态模型的联合表达。
  • 所有选项都在 packages/json-schema/src/lib.ts 有声明式校验,在 packages/json-schema/src/json-schema-emitter.ts 有对应实现,可在排查输出异常时对照源码定位。

【免费下载链接】typespec项目地址: https://gitcode.com/GitHub_Trending/ty/typespec

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询