结构体标签

未匹配的标注

结构体标签

结构体的字段除了名字和类型外,还可以有一个可选的标签(tag):它是一个附属于字段的字符串,可以是文档或其他的重要标记。比如在我们解析json或生成json文件时,常用到encoding/json包,它提供一些默认标签,例如:omitempty标签可以在序列化的时候忽略0值或者空值;而“-”标签的作用是不进行序列化,其效果和直接将结构体中的字段写成小写的效果一样。

type Info struct {
    Name string
    Age  int `json:"age,omitempty"`
    Sex  string
}

在序列化和反序列化的时候,也支持类型转化等操作。如

type Info struct {
    Name string
    Age  int   `json:"age,string"`
    //这样生成的json对象中,age就为字符串
    Sex  string
}

定义结构体时,可以通过这些默认标签来设定结构体成员变量,使之在序列化后得到特殊的输出。

示例代码:

type Student struct {
   Name string   `json:"-"`    //“-”作用是不进行序列化,效果和将结构体字段写成小写一样。
   Age  int      `json:"Age,omitempty"` // “omitempty”作用是在序列化的时候忽略0值或空值。
   Id int        `json:"idx,string"` // 序列化时,类型转化为string
   Sex  string   `json:"sex"`
}
func main() {
   stu := Student{Name:"Andy", Age:0, Id:100}

   ret, err:= json.Marshal(stu)
   if err != nil {
      panic(err)
   }
   fmt.Println("json info1 ret=", string(ret))
}

序列化应用tag

通过前面序列化章节编写的测试代码,我们可以看到。生成的序列化json字符串是将struct 结构体的字段名作为json字符串的key,将字段值作为value的。

这在实际应用过程中容易出现问题。为了方便导出包作用域,我们在定义结构体时,要将字段名的首字母大写,而实际应用中,当我们用json和外部API进行交互的时候, 其他语言并不像Go这样用大写和小写来控制变量的作用域。所以借助结构体标签,可以得到小写字母开头的字串。

很自然的,可以想到,将struct 结构体中的字段名改为小写字母不就可以解决这个冲突吗?但实际测试发现,如果转为小写,则丢失了包作用域,Marshal() 函数不能正常完成序列化,得到的往往是空值。后续再来测试。

这里,就需要用到我们上节提到的结构体标签tag来解决这一问题了。从新定义结构体类型。

注意语法: stu_name 一定要使用“ “ 包裹起来。

type Student struct {
   Name string    `json: "stu_name"`
   Id int            `json: "stu_id"`
   Age int            // 剩余两个字段不添加tag,用以比较
   Addr string
}

序列化方法与之前的序列化方法一致。使用json.Marshal() 可以直接得到json字符串,输出结果为:

stu序列化后 = {“stu_name”:”瞎么海”,”stu_id”:110,”Age”:33,”Addr”:”天津市海河”}

可以看到,此时json字符串的key值为“stu_name”和“stu_id”,是我们定义结构体时指定的tag。而没有指定tag的Age和Addr,key值依然是原来字段的名字。

如果改为小写会怎样呢?测试:

type Student struct {
   Name string    `json: "stu_name"`
   Id int            `json: "stu_id"`
   age int            // 将两个不添加tag的字段名改为小写
   addr string
}

当然,结构体变量赋值时也要指定小写的字段名进行赋值。

输出结果为:

stu序列化后 = {“stu_name”:”瞎么海”,”stu_id”:110}

可以看到,程序没有报错。但指定为小写字段名的两个字段age、addr没有成功转换为json字串。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~