You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang:如何用validator/v10的required_if验证依赖外层结构体的字段?

基于外层结构体字段实现嵌套结构体的条件验证(Go validator v10)

可以实现这种跨结构体的条件验证,核心是借助validator的自定义验证器功能,以下是具体操作步骤:

1. 编写自定义验证函数

需要编写一个自定义验证函数,它能获取外层Medicare结构体的CardType字段值,再判断当前CardExpiry.Day是否需要必填。

注意:验证函数中需要通过validator.FieldLevel的Parent()方法获取外层结构体实例,再提取CardType的值。

func requiredIfCardType(fl validator.FieldLevel) bool {
    // 获取外层Medicare结构体实例
    medicare, ok := fl.Parent().Interface().(Medicare)
    if !ok {
        return false // 类型断言失败时直接返回验证不通过
    }

    // 定义需要触发必填的CardType值
    requiredTypes := map[string]bool{
        "RECIPROCAL": true,
        "INTERIM":    true,
    }

    // 如果CardType属于目标类型,检查Day字段是否不为空
    if requiredTypes[medicare.CardType] {
        // 这里假设Day是int类型,根据实际类型调整判断逻辑
        return fl.Field().Int() != 0
    }

    // 非目标类型时,验证自动通过
    return true
}

2. 注册自定义验证器

在使用验证器前,需要把自定义函数注册到validator实例中:

import "github.com/go-playground/validator/v10"

var validate *validator.Validate

func init() {
    validate = validator.New()
    // 注册自定义验证器,指定标签名(比如required_if_cardtype)
    err := validate.RegisterValidation("required_if_cardtype", requiredIfCardType)
    if err != nil {
        panic(err)
    }
}

3. 给结构体字段添加自定义标签

在CardExpiry.Day字段上添加自定义验证标签,关联刚才注册的验证器:

type CardExpiry struct {
    Day   int    `json:"day" validate:"required_if_cardtype"`
    Month int    `json:"month"`
    Year  int    `json:"year"`
}

type Medicare struct {
    CardType   string     `json:"card_type" validate:"required,oneof=RECIPROCAL INTERIM OTHER"`
    CardExpiry CardExpiry `json:"card_expiry" validate:"required"`
}

4. 执行验证逻辑

正常解析JSON到结构体后,调用验证器的Struct()方法即可完成验证:

func main() {
    // 示例JSON载荷
    jsonData := []byte(`{"card_type":"RECIPROCAL","card_expiry":{"month":12,"year":2025}}`)
    var medicare Medicare
    err := json.Unmarshal(jsonData, &medicare)
    if err != nil {
        panic(err)
    }

    // 执行验证
    err = validate.Struct(medicare)
    if err != nil {
        // 处理验证错误
        for _, e := range err.(validator.ValidationErrors) {
            println("验证失败:", e.Field(), e.Tag())
        }
    }
}

补充说明

  • 如果Day是其他类型(比如string),需要调整自定义函数中的判断逻辑(比如fl.Field().String() != "")。
  • 若外层结构体是指针类型,需要先解引用再做类型断言:medicare, ok := fl.Parent().Interface().(*Medicare)。

内容的提问来源于stack exchange,提问作者samme4life

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 11:39:17