如何在invopop/jsonschema中通过Go结构体标签使用if/then/else?
使用invopop/jsonschema实现JSON Schema的if/then/else条件约束
问题分析
你当前的结构体标签写法不符合invopop/jsonschema库对if/then属性的解析规则——直接在数组字段的标签里写嵌套条件不会生效,因为数组元素的约束需要针对数组项(items)定义,而非数组本身。
正确实现方式
要实现当TransformerConfig的kind为convert_swim时,必须存在convert_swim_config字段的约束,需要:
- 为
TransformerConfig结构体单独定义条件约束 - 在
Boulou的Transformers字段中引用该结构体的约束
示例代码
package main import ( "fmt" "github.com/invopop/jsonschema" ) type TransformerConfig struct { Kind string `json:"kind" jsonschema:"required,enum=convert_swim,enum=other_kind"` ConvertSwimConfig *ConvertSwimConfig `json:"convert_swim_config"` OtherConfig *OtherConfig `json:"other_config"` } type ConvertSwimConfig struct { PoolSize int `json:"pool_size" jsonschema:"required,minimum=1"` } type OtherConfig struct { Threshold float64 `json:"threshold" jsonschema:"required,minimum=0.1"` } type Boulou struct { Name string `json:"name" jsonschema:"required,minLength=1,description=唯一名称"` Transformers []TransformerConfig `json:"transformers" jsonschema:"title=转换器"` } // 为TransformerConfig自定义JSON Schema规则 func (t TransformerConfig) JSONSchema() *jsonschema.Schema { // 先获取默认生成的Schema schema := jsonschema.Reflect(&t) // 添加if/then条件约束 schema.If = &jsonschema.Schema{ Properties: map[string]*jsonschema.Schema{ "kind": { Const: "convert_swim", }, }, Required: []string{"kind"}, } schema.Then = &jsonschema.Schema{ Required: []string{"convert_swim_config"}, } // 可选:添加else约束,比如当kind为other_kind时需要other_config schema.Else = &jsonschema.Schema{ Required: []string{"other_config"}, } return schema } func main() { schema := jsonschema.Reflect(&Boulou{}) b, _ := schema.MarshalJSON() fmt.Println(string(b)) }
关键说明
- invopop/jsonschema库支持通过结构体的
JSONSchema()方法自定义Schema规则,这是实现复杂条件约束的正确方式,而非仅依赖结构体标签 if部分需要明确指定要匹配的属性(如kind)及其值,同时标记该属性为必填,确保条件判断的准确性then部分定义满足条件时的约束(如必填convert_swim_config),else部分可定义不满足条件时的约束
JSON Schema条件规范(中文翻译)
JSON Schema的
if/then/else关键字用于实现条件约束:
if:定义一个条件Schema,当数据满足该Schema时,应用then的约束then:仅当if的条件满足时生效的约束else:仅当if的条件不满足时生效的约束
这些关键字可以嵌套使用,实现复杂的多条件逻辑。
内容的提问来源于stack exchange,提问作者Christophe
相关产品推荐
相关产品推荐

