尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

go-openapi/validate 使用指南:Loki 仓库内嵌的 Swagger 2.0 与 JSON Schema 校验器

go-openapi/validate 使用指南:Loki 仓库内嵌的 Swagger 2.0 与 JSON Schema 校验器 go-openapi/validate 使用指南Loki 仓库内嵌的 Swagger 2.0 与 JSON Schema 校验器【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/lokigo-openapi/validate 是一个面向 OpenAPI 2.0Swagger 2.0规范文档与 JSON Schema draft 4 的 Go 校验库在 Loki 仓库中以 vendor 形式内嵌于 vendor/github.com/go-openapi/validate版本为 v1.0.0见 go.sum 中的github.com/go-openapi/validate v1.0.0。本文从该库的官方 README 出发结合仓库内源码逐层拆解其三大能力——规范文档校验、Schema 数据校验、值级校验 helper帮助你在 Go 项目中正确引入并高效使用它。什么是 go-openapi/validatego-openapi/validate 是 go-swagger 生态中的核心校验组件其定位一句话可以概括A validator for OpenAPI v2 specifications and JSON schema draft 4.它提供三类能力来源README 的 Contents 一节Swagger 规范校验器校验 Swagger 2.0即 OpenAPI 2.0规范文档本身是否合法JSON Schema draft 4 校验器校验任意数据是否符合给定的 JSON Schema值级校验 helper 函数逐个校验单个值被 go-swagger 生成的代码直接调用。该包遵循 Apache-2.0 许可见 LICENSEAPI 已被官方声明为稳定README Status 一节API is stable.当前处于 v1.0.0 版本。在 Loki 仓库中的角色Loki 将 go-openapi/validate 及其依赖如go-openapi/spec、go-openapi/loads、go-openapi/strfmt、go-openapi/analysis、go-openapi/errors、go-openapi/swag见 go.mod 与 spec.go 的 import 列表以 vendor 目录方式冻结在仓库内作为间接依赖// indirect随 Loki 一起构建。这意味着你无需联网下载即可在本地查看、阅读该库的全部实现源码Loki 构建时使用的是仓库内固定版本行为可复现在阅读 Loki 或其他 go-swagger 相关 Go 代码时看到validate.Spec(...)、validate.Required(...)等调用即出自本包。安装与引入在任意 Go 项目中引入本库的标准方式README 的 Import 一节go get github.com/go-openapi/validate在 Loki 仓库中该依赖已通过 go module 机制锁定go.mod 第 357 行声明github.com/go-openapi/validate v1.0.0 // indirect并连同完整源码一起 vendored 到vendor/目录go build时无需额外操作。能力一Swagger 2.0 规范文档校验这是本包最核心的能力读取一份 Swagger/OpenAPI 2.0 规范文档JSON 或 YAML先按 Swagger 官方元 schema 做结构校验再执行一系列无法用 JSON Schema 表达的额外规则检查。入口函数源码 spec.go 提供了最简洁的入口// Spec validates an OpenAPI 2.0 specification document. // Returns an error flattening in a single standard error, all validation messages. func Spec(doc *loads.Document, formats strfmt.Registry, options ...Option) error { errs, _ /*warns*/ : NewSpecValidator(doc.Schema(), formats, options...).Validate(doc) if errs.HasErrors() { return errors.CompositeValidationError(errs.Errors...) } return nil }典型调用方式import ( github.com/go-openapi/loads github.com/go-openapi/validate github.com/go-openapi/strfmt ) doc, err : loads.Spec(swagger.json) // 或 swagger.yaml if err ! nil { // 文档无法解析 } if err : validate.Spec(doc, strfmt.Default); err ! nil { // 规范文档不合法err 为 CompositeValidationError // 内含所有校验错误信息 }如果你需要同时拿到警告warnings而不仅仅是错误则使用面向对象的入口NewSpecValidatorValidatespec.gov : validate.NewSpecValidator(doc.Schema(), strfmt.Default) errs, warns : v.Validate(doc) if errs.HasErrors() { /* ... */ } for _, w : range warns.Errors { /* ... */ }从源码看SpecValidator.Validate的流程大致为spec.go 起校验入参必须是*loads.Document否则直接返回invalidDocumentMsg()错误对文档做一份拷贝sd.Pristine()在拷贝上展开expand$ref保证调用方拿回的文档原样不变通过analysis.New(sd.Spec())建立规格分析器定位每个$ref、参数、响应、路径项的位置先按元 schema 做结构校验再做规则检查将$ref展开后发现的错误回定位到原始文档中的节点。元 schema 覆盖的结构约束根据 doc.go 的说明很多结构约束由 Swagger 官方元 schema 直接裁决校验器不重复实现例如collectionFormat必须是csv、ssv、tsv、pipes之一query/formData参数额外允许multibody参数则不允许携带各字段的type、required结构、paths的组织形式等基础结构。无法用 JSON Schema 表达的规则检查errors在元 schema 之外本包额外报告以下错误完整清单见 doc.go定义definition不能声明一个祖先模型已经定义过的属性定义的祖先不能是同一模型的子孙继承环检测路径唯一性每个 API 路径在考虑路径参数名后对每个方法应保持唯一例如GET:/petstore/{id}与GET:/petstore/{pet}会被视为重复路径——可通过关闭StrictPathParamUniqueness放宽见下文选项每个 security 引用中 scope 必须唯一security 定义中的 scope 也必须唯一discriminator 必须指向 schema 已定义且列入required的属性每个 security requirement 必须引用securityDefinitions中已声明的 scheme只有oauth2类型的 security requirement 允许列出 scopes其他 scheme 类型不得携带 scopes路径参数必须唯一且与路径模板占位符一一对应每个可被引用的定义必须确实存在引用否则视为未使用定义并警告required数组中列出的属性必须已在模型的properties中定义每个参数必须有唯一的nametype组合每个操作最多只能有 1 个body类型参数每个$ref必须指向有效的对象每个default值必须能通过其所属属性的 schema 校验所有array类型的 schema/definition 必须声明items路径参数必须声明为requiredheader 不得包含$refschema/property 中提供的example必须能通过对应 schema 校验。规则检查warnings以下情况只产生警告doc.go路径参数中不应包含{、}、\w等字符空路径未使用的 definitions对非 JSON 媒体类型不支持校验 examplesresponse 无 schema 却提供 examplesreadOnly属性不应出现在required中oauth2 security requirement 引用了其 scheme 未声明的 scope在非array类型的参数、header 或 items 上书写了collectionFormat。校验选项Opts 与 SetContinueOnErrorsoptions.go 定义了Opts结构选项默认值说明ContinueOnErrorsfalse为true时即使规范无效也继续报告所有错误适合完整错误报告为false时一旦发现无效即尽早退出校验更快。不影响最终校验状态StrictPathParamUniquenesstrue开启后严格校验路径唯一性把GET:/petstore/{id}与GET:/petstore/{pet}视为重复路径。当路径参数可能包含斜杠如GET:/v1/{shelve}与GET:/v1/{book}ID 形如shelve/*、shelve/*/book/*时建议关闭SkipSchemataResultfalse跳过 schema 校验结果收集其中ContinueOnErrors可通过包级函数SetContinueOnErrors(bool)全局调整options.go。需要注意该函数修改的是全局默认值不适合并发场景使用并发代码中应通过其他方式传递选项。安全提示WithPathLoader 限制文档加载当校验来自不可信来源的规范文档时可以使用WithPathLoader选项注入受限的文档加载器schema_option.go约束校验过程中解析$ref时允许加载的路径防止恶意$ref读取本地文件或外部资源。Spec与NewSpecValidator的文档注释都特别强调了这一点spec.go。能力二JSON Schema draft 4 数据校验除了校验规范文档本身本包还提供了完整的 JSON Schema draft 4 数据校验能力。入口AgainstSchemaschema.go 提供的AgainstSchema是最简洁的入口func AgainstSchema(schema *spec.Schema, data any, formats strfmt.Registry, options ...Option) error如果传入nil的*spec.Schema则使用一个 JSON Schema 作为默认 schema源码注释明确说明。深入SchemaValidator更底层的是SchemaValidatorschema.go它维护Path被校验值的位置采用传统的点分隔记法该字段已标记Deprecated因为属性名含点号时会产生歧义官方建议改用 JSON pointer 表示Schema*spec.Schema即待校验的 schemavalidators [8]valueValidator内部编排的一组值级校验器类型校验、通用约束、slice 约束、数字约束、字符串约束、格式约束等KnownFormats strfmt.Registry支持的格式注册表。NewSchemaValidator在 schema 非法时会panicschema.go源码注释为 Panics if the provided schema is invalid因此生产代码应确保传入 schema 是可信且解析成功的。此外NewSchemaValidator会对调用方持有的 schema 做深拷贝deepCloneSchema后再展开$ref避免污染调用方数据schema.go。Schema 校验器的内部分工从 validator.go 可以看到SchemaValidator由一组valueValidator协作完成校验它们各自负责一个维度并通过Applies(source any, kind reflect.Kind) bool决定是否对当前值生效校验器职责对应关键字basicCommonValidator通用约束default、enum见 validator.gobasicSliceValidator数组级约束maxItems、minItems、uniqueItems见 validator.gonumberValidator数字约束maximum、minimum、multipleOf见 validator.gostringValidator字符串约束maxLength、minLength、pattern见 validator.goformatValidator格式约束format如date-time、email见 formats.goitemsValidator数组元素校验items见 validator.goobjectValidator/sliceValidator等对象/数组结构properties、additionalProperties、allOf、anyOf、oneOf、not等见 object_validator.go、slice_validator.go从源码结构可以推断校验器对象与结果对象都通过sync.Pool复用validatorPools、redeem()/redeemChildren()等方法高并发校验场景下可显著减少对象分配NewSpecValidator默认开启WithRecycleValidators(true)spec.go。完整的 draft 4 词汇表支持README 与 doc.go 都强调本包支持完整的 JSON Schema 词汇表包括 Swagger 不支持的扩展关键字例如additionalItems、additionalPropertiesallOf、anyOf、oneOf、notpatternPropertiesdefinitions、$ref等相关常量定义见 helpers.go。它通过了完整的 JSON-Schema-Test-Suite 测试见 doc.go 中 It is tested against the full json-schema-testing-suite除可选部分大数 bignum、ECMA 正则等之外。已知限制包括最大支持math.MaxFloat64的数值范围不支持任意大数。能力三值级校验 helper 函数README 明确指出以下 helper 函数被 go-swagger 生成的代码直接使用。这些函数全部位于 values.go签名统一为func XXX(path, in string, ...) *errors.Validation——第一个参数是错误报告中显示的字段路径第二个参数in表示值所在位置如query、path、header、body。Helper 函数校验内容源码位置Required(path, in, data)值非空非零值values.goRequiredString(path, in, data)字符串非空values.goRequiredNumber(path, in, data)数字非零values.goReadOnly(ctx, path, in, data)只读属性约束values.goUniqueItems(path, in, data)数组元素唯一性values.goMaxItems(path, in, size, max)/MinItems(path, in, size, min)数组长度上下限values.goEnum(path, in, data, enum)/EnumCase(path, in, data, enum, caseSensitive)枚举取值后者可选大小写敏感values.goPattern(path, in, data, pattern)正则匹配values.goMinLength(path, in, data, min)/MaxLength(path, in, data, max)字符串长度上下限values.goMinimum(...)/Maximum(...)/MultipleOf(...)数值下界/上界/倍数含Int、Uint、NativeType变体values.goFormatOf(path, in, format, data, registry)按strfmt.Registry校验格式values.go典型用法与 go-swagger 生成代码中的模式一致import github.com/go-openapi/validate // 校验必填字符串 if err : validate.RequiredString(name, query, name); err ! nil { return err } // 校验枚举 if err : validate.Enum(status, query, status, []any{active, inactive}); err ! nil { return err } // 校验正则 if err : validate.Pattern(id, path, id, ^[a-zA-Z0-9-]$); err ! nil { return err } // 校验数组元素唯一 if err : validate.UniqueItems(tags, body, tags); err ! nil { return err }此外 values.go 还提供IsValueValidAgainstRange(val, typeName, format, prefix, path)用于在已知类型与格式的前提下判断值是否落在合法数值区间内。内部实现的数值处理细节从源码看数值校验内部做了精细的类型分派helpers.goasInt64/asUint64/asFloat64分别将任意any值转换为对应的数值类型再比较Maximum/Minimum/MultipleOf的Int与Uint变体针对原生整数类型做了专门的实现避免浮点误差如 values.go 中MaximumInt、MaximumUint、MultipleOfInt、MultipleOfUintNativeType变体MaximumNativeType等则直接基于反射处理原生 Go 类型。这意味着即使上层传入的是int64、uint64等原生整数也能获得精确的区间与倍数判断不会因中间转float64而产生精度损失。结果模型Result 与 Located 错误所有校验器规范级与 schema 级统一返回*Resultresult.go它同时承载 errors 与 warningstype Result struct { errors []error warnings []error // 以及用于 schema 追踪的字段/条目位置映射 }常用方法result.go方法说明HasErrors()/HasWarnings()是否有错误/警告IsValid()无错误即有效AsError()将结果转换为标准error接口Merge(others...)合并多个结果LocatedErrors()/LocatedWarnings()返回带位置JSON pointer的错误/警告列表result.goLocated结构result.go将错误与文档中的 JSON pointer 位置关联方便调用方直接定位到规范文档的具体节点——这正是SpecValidator.Validate内部展开$ref后再把错误回定位到原始文档这一设计spec.go的产物。常见问题 FAQREADME 的 FAQ 明确回答了一个高频问题Does this library support OpenAPI 3?No. This package currently only supports OpenAPI 2.0 (aka Swagger 2.0). There is no plan to make it evolve toward supporting OpenAPI 3.x.即本库不支持 OpenAPI 3.x也没有演进到 OpenAPI 3 的计划。如果你的项目需要校验 OpenAPI 3 规范需要另行选择其他方案README 提到 go-openapi 生态中曾有一个早期实验性项目 spec3但它不是本包的组成部分本仓库中也不包含该模块。在 Loki 仓库中继续深入如果你想进一步研究该库的底层实现Loki 仓库内可直接阅读以下文件vendor/github.com/go-openapi/validate/spec.go规范校验入口Spec、SpecValidator与完整校验流程vendor/github.com/go-openapi/validate/schema.goSchemaValidator、AgainstSchema与 schema 深拷贝/展开逻辑vendor/github.com/go-openapi/validate/values.go全部值级 helper 函数实现vendor/github.com/go-openapi/validate/validator.govalueValidator家族common / slice / number / string / header / param / itemsvendor/github.com/go-openapi/validate/object_validator.go 与 slice_validator.go对象与数组的结构化校验vendor/github.com/go-openapi/validate/doc.go错误/警告规则的完整官方清单vendor/github.com/go-openapi/validate/options.go 与 schema_option.go校验选项体系vendor/github.com/go-openapi/validate/result.goResult结果模型与位置追踪。小结go-openapi/validate 是一个稳定、专注的校验库面向 OpenAPI 2.0 规范的Spec/SpecValidator校验链覆盖了元 schema 结构约束与数十条额外规则错误与警告两级面向 JSON Schema draft 4 的SchemaValidator支持完整词汇表并经过官方测试套件验证面向单值的Required/Enum/Pattern/Minimum等 helper 则是 go-swagger 生成代码的运行时校验基石。其源码实现中深拷贝后展开$ref、错误回定位 JSON pointer、validator 对象池复用等设计也值得 Go 开发者作为高质量库的实现范本阅读。【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表