CLI开发工具【免费下载链接】cliThe Docker CLI项目地址https://gitcode.com/gh_mirrors/cli5/cli点击查看免费下载导读本文围绕 Docker CLI 仓库中引入的第三方 Go 依赖 santhosh-tekuri/jsonschema v6 展开这是一款以“先编译、后校验”为核心设计、完整支持 JSON Schema 各主要 draft04/06/07/2019-09/2020-12的 Go 实现。读完本文你将掌握它的编译器 APICompiler、格式与内容断言、自定义词汇Vocabulary、可内省的层级化错误模型以及随库发布的命令行工具jv的全部用法同时我们也会结合仓库源码说明 Docker CLI 是如何把它用于 Compose 文件校验的。说明本文仓库中实际 vendor 的版本为 v6.0.3见 vendor/modules.txt而jv命令行工具独立版本为 v0.7.0。一、库的整体能力一览根据 README.md 的“Library Features”该库的能力可归纳为六个方面能力类别说明规范符合度通过 JSON-Schema-Test-Suite排除 optional 用例覆盖 draft-04 / draft-06 / draft-07 / draft/2019-09 / draft/2020-12循环陷阱检测检测$schema循环与校验引用循环避免校验过程死循环自定义扩展自定义$schemaURL、自定义正则引擎、自定义格式format、自定义词汇vocabulary格式断言draft ≥ 2019-09 需显式开启内置常见格式支持自定义格式注册内容断言draft ≥ 7 需显式开启支持contentEncoding/contentMediaType/contentSchema错误模型错误可内省、具有层级结构可用#作 alt 展示输出支持 flag / basic / detailed 三种结构从源码结构看模块划分清晰compiler.go 负责编译、validator.go 负责校验、draft.go 定义各版本规范、format.go 与 content.go 提供断言实现、output.go 负责错误输出、vocab.go 提供自定义词汇接口。二、核心 APICompiler 编译 Schema 并执行校验2.1 编译与校验的基本流程该库的理念是“编译一次、校验多次”先用jsonschema.NewCompiler()创建编译器调用Compile(loc)把 Schema 编译为*Schema之后用Schema.Validate(v)反复校验任意 JSON 值。import github.com/santhosh-tekuri/jsonschema/v6 func main() { // 1. 编译 schema.json支持文件路径或 file:// URL c : jsonschema.NewCompiler() schema, err : c.Compile(schema.json) if err ! nil { panic(err) } // 2. 校验任意 JSON 值可为 map[string]any / []any / 基础类型 var doc any // 通过 jsonschema.UnmarshalJSON 解析得到 if err : schema.Validate(doc); err ! nil { panic(err) // err 为 *jsonschema.ValidationError可内省 } }入口 API 定义见 compiler.goCompiler结构体与 compiler.goCompile方法。Schema是编译后的表示内部按关键字把约束拆解为字段如Types、Properties、Items、Minimum等定义见 schema.go。若希望在全局变量初始化阶段编译可用MustCompile(loc)编译失败时直接 panic见 compiler.go。2.2 数值精度与 JSON 解析v6/loader.go 提供了UnmarshalJSON(r io.Reader) (any, error)它使用json.Decoder的UseNumber()保证大整数/高精度小数不被float64截断同时会检查顶层值之后是否还有多余内容。数值比较在内部通过big.Rat进行见 validator.go因此multipleOf、minimum等关键字对超大数值也保持精确。2.3 默认 Draft 与多版本选择Schema 依据其$schema字段选择规范版本若缺失则默认使用库当前支持的最新 draftdraft/2020-12。为保证长期行为稳定文档建议显式指定默认 draftc : jsonschema.NewCompiler() c.DefaultDraft(jsonschema.Draft4) // 缺失 $schema 时按 draft-04 编译各版本定义见 draft.goDraft4、Draft6、Draft7、Draft2019、Draft2020其中 draft ≥ 2019 引入$defs、dependentSchemas、unevaluatedProperties/Items、contentSchema、$vocabulary等关键字draft-2020 进一步引入prefixItems。每个版本的元模式metaschema已内嵌在库中见 metaschemas 目录无需联网即可加载。2.4 资源加载与引用解析AddResource(url string, doc any)把内存中的 JSON 文档注册为可被$ref引用的资源见 compiler.go。UseLoader(loader URLLoader)替换默认的资源加载器。默认实现FileLoader只支持文件 URLSchemeURLLoader可按 scheme 分发到多个加载器见 loader.go。引用解析时库会先把文档拆分为“资源”resource并收集锚点anchor支持$anchor、$dynamicAnchor、$dynamicRef、$recursiveRef等相关逻辑见 root.go。三、格式断言Format Assertions3.1 开关与默认行为format关键字在 JSON Schema 中默认只作“注解”而非“断言”。本库通过Compiler.AssertFormat()显式开启格式校验c : jsonschema.NewCompiler() c.AssertFormat() // 强制启用格式断言各版本的默认行为见 compiler.godraft-07默认启用draft/2019-09默认禁用除非元模式声明format词汇为必需draft/2020-12默认禁用除非元模式声明format-assertion词汇为必需。3.2 内置格式清单内置格式注册在 format.go与 README 中“built-in formats”一一对应类别格式标识符regex、uuid网络ipv4、ipv6、hostname、email时间date、time、date-time、duration指针json-pointer、relative-json-pointerURI 族uri、uri-reference、uri-template、iri、iri-reference其他period、semver每个格式在 format.go 中都有独立实现函数例如uuid按 RFC 4122 校验 8-4-4-4-12 的十六进制分组、ipv4拒绝前导零与越界十进制、semver按语义化版本语法校验主/次/修订号及预发布与构建元数据。若格式值类型不匹配如对数字应用date校验器直接放行。3.3 注册自定义格式type MyFormat struct{} func (MyFormat) Validate(v any) error { s, ok : v.(string) if !ok { return nil } if !strings.HasPrefix(s, my-) { return fmt.Errorf(must start with my-) } return nil } c : jsonschema.NewCompiler() c.RegisterFormat(jsonschema.Format{Name: my-format, Validate: MyFormat{}.Validate})注意名为regex的格式不可被覆盖见 compiler.go对 draft ≥ 2019-09格式断言默认关闭需要配合AssertFormat()。四、内容断言Content Assertions内容断言用于校验字符串“内部承载的内容”由三个关键字构成contentEncoding、contentMediaType、contentSchema见 compiler.go。默认全部关闭需调用Compiler.AssertContent()开启适用于 draft ≥ 7。4.1 内置实现contentEncoding: base64内置解码器使用标准 base64 解码见 content.go。contentMediaType: application/json内置媒体类型可校验字节流是否为合法 JSON并支持反序列化为 JSON 值以继续套用contentSchema见 content.go。一个典型场景是“字符串里嵌 JSON再对它做模式校验”{ type: string, contentEncoding: base64, contentMediaType: application/json, contentSchema: { type: object, required: [name] } }此时实例值必须是 base64 编码的 JSON 字符串解码后还需满足contentSchema。校验器实现位于 validator.go先按contentEncoding解码再按contentMediaType验证或反序列化最后用contentSchema校验反序列化结果。4.2 注册自定义内容断言// 自定义 contentEncoding c.RegisterContentEncoding(jsonschema.Decoder{ Name: hex, Decode: func(s string) ([]byte, error) { /* 十六进制解码 */ }, }) // 自定义 contentMediaType c.RegisterContentMediaType(jsonschema.MediaType{ Name: application/x-custom, Validate: func(b []byte) error { /* 字节校验 */ }, })接口定义见 content.goDecoder需提供DecodeMediaType需提供Validate若该媒体类型兼容 JSON 还可提供UnmarshalJSON供contentSchema使用。五、自定义正则引擎默认情况下pattern、patternProperties等关键字使用 Go 标准库regexp。若需要 ECMA-262 等更贴近 JSON Schema 规范语义的正则语法可替换引擎type MyRegexpEngine struct{} // 实现 jsonschema.RegexpEngine 接口 // func (e MyRegexpEngine) Compile(s string) (jsonschema.Regexp, error) c : jsonschema.NewCompiler() c.UseRegexpEngine(MyRegexpEngine{}.Compile) // 必须在编译任何 Schema 之前调用接口定义见 compiler.goRegexp只需实现MatchString与String。六、自定义词汇Vocabulary与混合方言6.1 基于词汇的校验体系draft/2019-09 起JSON Schema 以“词汇vocabulary”为单位组织关键字。本库将各关键字按词汇归属编译见 objcompiler.go例如 draft-2020-12 支持core、applicator、unevaluated、validation、meta-data、format-annotation、format-assertion、content等词汇见 draft.go。6.2 注册自定义词汇通过Compiler.RegisterVocabulary注册并在 Schema 中用$vocabulary声明draft ≥ 2019-09或通过AssertVocabs()强制启用draft ≤ 7vocab : jsonschema.Vocabulary{ URL: https://example.com/vocab/my-vocab, Schema: myVocabSchema, // 校验本词汇关键字语法的模式 Subschemas: []jsonschema.SchemaPath{}, // 本词汇引入的子模式位置 Compile: func(ctx *jsonschema.CompilerContext, obj map[string]any) (jsonschema.SchemaExt, error) { // 从 obj 中提取本词汇的关键字编译为 SchemaExt return nil, nil }, } c : jsonschema.NewCompiler() c.RegisterVocabulary(vocab) c.AssertVocabs() // draft ≤ 7 时需要此开关Vocabulary与SchemaExt接口定义见 vocab.go。SchemaExt.Validate在校验阶段被调用可通过ValidatorContext报告错误、标记已评估属性/元素或递归校验子值见 vocab.go。SchemaPath用于声明子模式在文档中的可能位置如properties/*、items/[]定义见 position.go。6.3 混合方言支持不同资源可以声明不同的$schema库会按资源粒度记录方言dialect并在引用解析时正确切换见 roots.go从而在同一份 Schema 文档树中混用多个 draft 关键字。七、错误模型可内省、有层级的 ValidationError7.1 错误结构校验失败时Schema.Validate返回*jsonschema.ValidationError定义见 validator.go包含四个字段SchemaURL出错位置的绝对已解引用Schema 位置InstanceLocation实例中出错值的位置token 数组可拼成 JSON PointerErrorKind错误种类Causes嵌套子错误。ErrorKind是接口KeywordPath()与LocalizedString(*message.Printer)全部内建错误种类位于 kind/kind.go例如Type、Enum、Const、Required、Minimum、UniqueItems、AnyOf、OneOf、RefCycle等。应用侧可用errors.AsType*jsonschema.ValidationError提取后逐层遍历实现“最具体错误”定位Docker CLI 的 Compose 校验正是这样做的见下文。7.2 三种结构化输出除文本化错误信息外ValidationError还提供三种 JSON 友好的结构化输出见 output.go输出方法结构flagFlagOutput()仅{valid: false}basicBasicOutput()扁平列表每个输出单元带keywordLocation、instanceLocation、errordetailedDetailedOutput()按 Schema 结构组织的嵌套树含absoluteKeywordLocation输出单元OutputUnit字段见 output.go。README 提到错误层级可用#作“alternative display”——即LocalizedGoString会在错误信息中附上简写的 Schema 位置如S#/properties/name帮助定位。八、命令行工具 jv独立版本 v0.7.08.1 安装go install github.com/santhosh-tekuri/jsonschema/cmd/jvlatestjv与库本体独立版本号管理git tag 形如cmd/jv/v0.7.0。8.2 用法与选项Usage: jv [OPTIONS] SCHEMA [INSTANCE...]选项说明-c, --assert-content对 draft ≥ 7 启用内容断言-f, --assert-format对 draft ≥ 2019 启用格式断言--cacert pem-file使用指定 PEM 文件验证对端证书文件可含多个 CA 证书-d, --draft version缺失$schema时使用的 draft合法值4、6、7、2019、2020默认2020-h, --help打印帮助-k, --insecure使用不安全的 TLS 连接跳过证书验证-o, --output format输出格式simple、alt、flag、basic、detailed默认simple-q, --quiet不打印错误-v, --version打印构建信息8.3 关键行为退出码校验错误返回1用法错误返回2。同时校验 Schema 与多个实例jv schema.json a.json b.json可一次校验多个实例文件。JSON 与 YAML 均支持Schema 与实例都可以是 YAML 文件。标准输入使用-作为实例参数从 stdin 读取。quiet 模式-q不打印错误可与脚本结合仅依赖退出码-o flag输出结构化布尔结果。HTTP(S) URLSchema 位置可直接传https://...需要自定义 CA 时用--cacert跳过证书校验时用--insecure。九、仓库实战Docker CLI 如何用它校验 Compose 文件作为“锦上添花”的源码证据本仓库在 cli/compose/schema/schema.go 中直接使用了该库来校验 Compose 配置通过//go:embed data/config_schema_v*.json内嵌各版本 Compose 配置模式见 schema.goValidate(config map[string]any, version string)中读取对应版本模式 →jsonschema.UnmarshalJSON解析 →jsonschema.NewCompiler()编译 → 注册两个自定义格式ports与duration前者委托nat.ParsePortSpec后者委托time.ParseDuration见 schema.go→compiler.AddResource(schema.json, schemaDoc)→Compile→schema.Validate见 schema.go校验失败后利用errors.AsType[*jsonschema.ValidationError]提取错误通过flattenErrors展开层级并用specificity基于InstanceLocation长度挑选“最具体错误”把got X, want Y之类信息转成field: must be ...的人类可读文案见 schema.go。该校验在 Compose 加载流程中被调用见 cli/compose/loader/loader.go 的schema.Validate(configDict, configDetails.Version)是理解“先编译、后校验”与错误内省能力在真实工程中价值的最佳范例。十、循环检测与健壮性README 明确列出两项循环陷阱检测能力$schema循环加载$schema指向的元模式时维护 cycle 集合若元模式又引用回自身则报MetaSchemaCycleError见 loader.go校验循环$ref/$recursiveRef/$dynamicRef形成的引用环由scope的checkCycle在运行时拦截报RefCycle错误而非无限递归见 validator.go。同时库还提供一系列明确的错误类型LoadURLError、UnsupportedDraftError、DuplicateIDError、DuplicateAnchorError、AnchorNotFoundError、UnsupportedVocabularyError等分散于 loader.go、roots.go、root.go方便调用方精确区分失败原因。结语santhosh-tekuri/jsonschema v6 以“编译-校验”两阶段模型为核心在保持对 JSON Schema 主流版本完整支持的同时通过格式/内容断言、自定义正则、自定义词汇与结构化错误输出把扩展点都设计为公开的 Go 接口jv命令行工具则把同样的能力平移到脚本与 CI 场景。无论是直接集成到 Go 服务还是像 Docker CLI 这样用它校验配置文件的合法性你都可以基于本文的 API 与源码路径快速上手并深入调试。赞分享CLI开发工具【免费下载链接】cliThe Docker CLI项目地址https://gitcode.com/gh_mirrors/cli5/cli点击查看免费下载相关推荐Grafana Tempo 中的 JSON Schema 校验利器jsonschema v6 库特性全解与 jv CLI 实战指南Grafana Tempo 中的 JSON Schema 校验利器jsonschema v6 库特性全解与 jv CLI 实战指南 本文以 Grafana T后端可观测性链路追踪Go 语言 JSON Schema 校验全攻略gojsonschemav1.2.0库解析与实战Go 语言 JSON Schema 校验全攻略gojsonschemav1.2.0库解析与实战 本文以 KubeSphere 仓库中 vendored 的后端云原生容器编排微服务go-swagger validate 命令完全指南使用 JSON Schema 与语义规则校验 Swagger 2.0 规范go swagger validate 命令完全指南使用 JSON Schema 与语义规则校验 Swagger 2.0 规范 swagger validat代码生成开发工具后端API设计创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考