检查结构字段是否为空



我想在将 JSON 对象解组后迭代struct的字段,并检查未设置值的字段(即为空(。

我可以获取每个字段的值并将其与相应类型的reflect.Zero值进行比较

json.Unmarshal([]byte(str), &res)
s := reflect.ValueOf(&res).Elem()
typeOfT := s.Type()
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
v := reflect.ValueOf(f.Interface())
if (reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())) {
....

但问题当然在于,这对boolint价值观不起作用。 如果在 JSON 中将bool字段设置为false或将int字段设置为0,则它们将等于其类型的零值。上述检查将认为字段未初始化,即使它们实际上设置了值。

我知道解决此问题的一种方法是使用指针,但我只是不明白在这种情况下这怎么可能,因为我使用的是reflect.Value类型,而不是实际的struct

正如你提到的,你可以使用指针。

json包可以为您处理将值解组为指针。您没有包含您尝试解组的 json 有效负载,或者您正在解组的结构,所以我编造了一个示例。

// json
{
"foo": true,
"number_of_foos": 14
}
// go struct
type Foo struct {
Present bool `json:"foo"`
Num     int  `json:"number_of_foos"`
}

在这里,如果缺少键foonumber_of_foos,那么正如您正确观察到的那样,将使用零值(false/0(。一般来说,最好的建议是利用零值。创建结构,使false的零值有用,而不是痛苦。 这并不总是可能的,因此将Foo结构中的字段类型更改为指针将允许您检查您所追求的 3 种情况。

  1. 目前
  2. 存在和零
  3. 失踪

这是带有指针的相同结构:

// go struct
type Foo struct {
Present *bool `json:"foo"`
Num     *int  `json:"number_of_foos"`
}

现在,您可以使用fooStruct.Present != nil检查该值是否存在,如果该条件成立,则可以假定字段中的值是您想要的值。

无需使用反射包。

另一种相同的方法是实现json.Unmarshaler

type MaybeInt struct {
Present bool
Value   int
}
func (i *MaybeInt) UnmarshalJSON(bs []byte) error {
if e := json.Unmarshal(bs, &i.Value); e != nil {
return e
}
i.Present = true
return nil
}

然后,您可以在顶级结构中使用MaybeInt

type Top struct {
N MaybeInt `json:"n"`
M MaybeInt `json:"m"`
}
func main() {
t := Top{}
if e := json.Unmarshal([]byte(` { "n": 4930 } `), &t); e != nil {
panic(e)
}
fmt.Println(t.N, t.M)
}

看它在操场上工作

尝试使用 golang 验证器包。验证器包提供了一个必需的属性,该属性可能会根据您的需要完成所需的工作。所需属性的官方文档指出:

这将验证该值不是数据类型默认零值。对于数字,确保值不为零。对于字符串确保值不""。对于切片、映射、指针、接口、通道和函数,确保值不为零。

说明相同情况的示例可以在以下位置看到:https://github.com/go-playground/validator/blob/v9/_examples/struct-level/main.go。

希望这能解决您的要求。

相关内容

  • 没有找到相关文章

最新更新