Go语言解析JSON如何在字段缺失或为null时自动报错无需逐个if校验
Go解析JSON时实现必填字段缺失/值为null自动报错的方案
Go标准库encoding/json默认不会对缺失的必填字段、字段值为null的场景抛出错误,你可以通过以下两种主流方案实现需求,无需手动编写逐个校验字段的if语句:
方案1:引入校验库统一校验(最常用)
使用go-playground/validator校验库,给结构体字段加validate:"required"标签,JSON解析完成后仅需调用一次校验方法即可完成所有必填字段的校验,自动识别字段缺失、值为null的场景并返回错误。
示例代码如下:
package main import ( "encoding/json" "fmt" "github.com/go-playground/validator/v10" ) var validate *validator.Validate func init() { // 初始化校验器 validate = validator.New() // 配置校验时读取json标签作为字段名,可选配置 validate.SetTagName("json") } type Bird struct { Species string `json:"birdType" validate:"required"` Description string `json:"what it does" validate:"required"` } func main() { birdJson := `{"birdType": "pigeon"}` var bird Bird if err := json.Unmarshal([]byte(birdJson), &bird); err != nil { fmt.Println("JSON解析错误:", err) return } // 统一校验必填字段 if err := validate.Struct(bird); err != nil { fmt.Println("字段校验错误:", err) // 这里会返回Description字段缺失的错误 return } fmt.Println(bird) }
方案2:自定义反序列化方法(无第三方依赖)
如果不想引入第三方依赖,可以给结构体实现UnmarshalJSON方法,在反序列化逻辑中统一校验字段是否存在、值是否为null,解析时自动触发校验:
package main import ( "encoding/json" "errors" "fmt" ) type Bird struct { Species string `json:"birdType"` Description string `json:"what it does"` } func (b *Bird) UnmarshalJSON(data []byte) error { // 定义别名避免递归反序列化 type Alias Bird tmp := &struct { *Alias // 用指针类型接收字段,用来判断是否缺失/为null Species *string `json:"birdType"` Description *string `json:"what it does"` }{ Alias: (*Alias)(b), } if err := json.Unmarshal(data, tmp); err != nil { return err } // 校验必填字段 if tmp.Species == nil { return errors.New("必填字段birdType缺失或值为null") } if tmp.Description == nil { return errors.New("必填字段what it does缺失或值为null") } // 赋值到原始结构体 b.Species = *tmp.Species b.Description = *tmp.Description return nil } func main() { birdJson := `{"birdType": "pigeon"}` var bird Bird // 反序列化时自动触发校验,缺失字段直接返回错误 if err := json.Unmarshal([]byte(birdJson), &bird); err != nil { fmt.Println("错误:", err) return } fmt.Println(bird) }
注意:标准库
encoding/json提供的DisallowUnknownFields()方法是用来禁止JSON中出现结构体未定义的多余字段,和本文提到的必填字段校验逻辑相反,不要混淆使用。
内容的提问来源于stack exchange,提问作者August
相关产品推荐
相关产品推荐

