golang官方json包, 提供了关键字'omitempty', 而有时我们的需求是要求某个字段必须存在, 否则就认为反序列化失败. 本文提供了一个思路, 以'required'为必须关键字, 用reflect来判断反序列化后的结果是否包含必须字段. 代码如下:
package main
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
)
// Binding Binding
// 判断结构体的必要字段是否存在
// 在官方支持omitempty关键字的
// 基础上增加required关键字
// tag: json
// key: omitempty/required
func Binding(i interface{}) error {
elems := reflect.ValueOf(i).Elem()
rtypeof := elems.Type()
if rtypeof.Kind() != reflect.Struct {
return errors.New("Type of i is not struct")
}
for i := 0; i < elems.NumField(); i++ {
vfield := elems.Field(i)
tfield := rtypeof.Field(i)
var tag string
tags := tfield.Tag.Get("json")
if index := strings.Index(tags, ","); index != -1 {
tag = tags[index+1:]
}
if tag == "required" {
if vfield.Kind() == reflect.Ptr {
if vfield.IsNil() {
return errors.New("Field '" + tfield.Name + "' is required")
}
} else if vfield.Kind() == reflect.String {
if vfield.IsZero() {
return errors.New("Field '" + tfield.Name + "' is required")
}
} else if vfield.Kind() == reflect.Interface {
if vfield.IsNil() {
return errors.New("Field '" + tfield.Name + "' is required")
}
} else {
return errors.New("Field type error")
}
}
}
return nil
}
type Student struct {
Name string `json:"name,required"`
Age *int `json:"age,required"`
Info interface{} `json:"info,required"`
}
func main() {
strs := []string{
"{\"name\":\"Bob\",\"age\":10}",
"{\"name\":\"Bob\",\"info\":\"info aaaaaaa\"}",
"{\"age\":10,\"info\":\"info aaaaaaa\"}",
"{\"name\":\"Bob\",\"age\":10,\"info\":\"info aaaaaaa\"}",
}
for i := 0; i < len(strs); i++ {
s := &Student{}
if err := json.Unmarshal([]byte(strs[i]), s); err != nil {
continue
}
if err := Binding(s); err != nil {
fmt.Println(strs[i], "lack of fileds, errMsg:", err.Error())
continue
}
fmt.Println(strs[i], "perfect")
}
}
结果如下:
在实际项目里, 远比这复杂, 本文提供了一个这样的思路, 希望能起到抛砖引玉的效果.
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)