Skip to content

Repository files navigation

jsonschema

jsonschema 从 Go 类型生成可直接用于 github.com/google/jsonschema-go 的 JSON Schema,并提供基于同一 schema 的运行时校验。

它内部使用 github.com/invopop/jsonschema 负责反射 Go 类型,再转换为 google/jsonschema-go/jsonschema.Schema。适合需要把 Go 结构体同时用于 schema 输出和参数校验的场景,例如 MCP tool 的 InputSchema / OutputSchema

选型考虑

这个包同时使用 invopop/jsonschemagoogle/jsonschema-go,是为了把两边各自擅长的部分组合起来:

  • google/jsonschema-go 是官方 MCP Go SDK 使用的 schema 类型。MCP tool 的 InputSchema / OutputSchema 可以直接接收它,因此最终输出 Google Schema 能减少适配层。
  • invopop/jsonschema 的 Go 类型反射和 tag 支持更完整,适合从结构体生成较丰富的 JSON Schema,包括字段描述、枚举、长度、数值范围、数组约束和扩展字段等。
  • 本包先用 invopop/jsonschema 生成完整 schema,再通过 JSON 字节重新反序列化为 google/jsonschema-go 的 Schema。这样既保留了生成能力,也得到 MCP 生态原生支持的类型。

安装

go get github.com/dpchan/jsonschema

快速开始

package main

import (
	"fmt"
	"log"

	"github.com/dpchan/jsonschema"
)

type LookupParams struct {
	City string `json:"city" jsonschema:"description=城市名称"`
	Days int    `json:"days,omitempty" jsonschema:"description=预报天数"`
}

func main() {
	s := jsonschema.Schema[LookupParams](
		jsonschema.WithTitle("天气查询参数"),
		jsonschema.WithDescription("查询指定城市天气所需的参数"),
	)

	if err := jsonschema.Validate(s, map[string]any{
		"city": "Shanghai",
		"days": 2,
	}); err != nil {
		log.Fatal(err)
	}

	fmt.Println(s.Title)
}

API

Schema

func Schema[T any](opts ...Option) *google.Schema

Schema[T] 从 Go 类型 T 生成 github.com/google/jsonschema-go/jsonschema.Schema。结构体字段的名称、必填规则和描述等信息主要来自 jsonjsonschema 等 tag。

T 是接口类型(例如 any)时返回 nil,表示没有可用 schema。

Option

当前内置的 Option 用于设置 schema 元数据:

  • WithID(id string):设置 $id
  • WithTitle(title string):设置 title
  • WithDescription(desc string):设置 description

Validate

func Validate(s *google.Schema, instance any) error

Validate 校验 instance 是否符合给定 schema。内部会缓存已解析的 schema,重复校验同一个 schema 时不需要反复解析。

字段标签

字段定义遵循 invopop/jsonschema 的 tag 规则。jsonschemajsonschema_extras 标签都需要写成 invopop 支持的格式;本包不会定义或解析额外的标签语法。

常用写法:

type Params struct {
	Name string `json:"name" jsonschema:"description=用户名称"`
	Age  int    `json:"age,omitempty" jsonschema:"description=年龄"`
}

json:"name" 控制 schema 中的属性名。没有 omitempty 的字段通常会进入 required

jsonschema:"description=..." 用于设置字段描述。更多 tag 能力请以 invopop/jsonschema 的文档和行为为准。

示例

  • examples/jsonschema_tags:展示常见 jsonschema tag 生成效果和校验用法。
  • examples/validate:展示 Validate 对合法输入、缺字段、类型错误、枚举错误和嵌套约束的校验结果。
  • examples/mcp_google_schema:展示如何把生成的 Google Schema 用在官方 MCP Go SDK 的 tool 定义中。

第三方依赖

  • github.com/invopop/jsonschema:用于从 Go 类型生成完整 JSON Schema。jsonschemajsonschema_extras 标签语法以它为准。许可证信息以其仓库为准。
  • github.com/google/jsonschema-go:作为最终 Schema 类型,并用于解析和校验。许可证信息以其仓库为准。
  • github.com/modelcontextprotocol/go-sdk:只在 examples/mcp_google_schema 独立示例模块中使用,不是根包运行时依赖。许可证信息以其仓库为准。

行为说明

  • 生成失败时会 panic。这通常表示 Go 类型本身不适合生成 JSON Schema,建议在程序启动阶段生成并暴露问题。
  • 生成结果会设置 additionalPropertiesnil,避免额外属性策略覆盖调用方或下游库的默认行为。
  • Schema 返回的是 google/jsonschema-go/jsonschema.Schema,可直接传给依赖 Google Schema 类型的库。

潜在风险点

  • Schema[any]() 会返回 nil,表示没有可用 schema。调用方不应直接把 nil 传给 Validate,否则当前实现会在解析 schema 时 panic。
  • Validate 会按 *google.Schema 指针缓存解析结果。schema 第一次用于校验后,应视为只读对象,不要继续修改 PropertiesRequired 等字段,否则缓存结果可能和修改后的 schema 不一致。
  • 默认校验器会缓存每个出现过的 schema 指针。如果在请求路径中反复调用 Schema[T]() 并立即校验,会产生大量不同的 schema 指针,缓存可能持续增长。建议在程序启动阶段生成 schema,并在后续请求中复用。
  • 包级文档目前放在 schema.go 顶部。随着文档继续变长,可以考虑迁移到单独的 doc.go,让入口代码和包文档分离。

许可证

本项目源码使用 MIT License。详见 LICENSE

第三方依赖不包含在本项目许可证授权范围内,其使用、分发和再授权须遵守各自许可证。

About

use github.com/invopop/jsonschema to generator https://github.com/google/jsonschema-go

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages