个人学习总结,如有不对的地方也欢迎指出,一起交流学习,共同进步
结构体转Json
type Person1 struct {
Name string `json:"name"`
Age int `json:"age"`
Addr string `json:"addr"`
}
type Person2 struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
Addr string `json:"addr"`
}
func main() {
var ps Person1
//var ps Person2
ps.Name = "ming"
ps.Addr = "Beijing"
psByte, _ := json.Marshal(ps)
fmt.Printf("%s\n", string(psByte))
}
omitempty零值
Person1: {"name":"ming","age":0,"addr":"Beijing"}
Person2: {"name":"ming","addr":"Beijing"}
omitempty
Json转结构体
omitempty
omitemptyjson.Unmarshal
Person: {"name": "ming", "addr": "Beijing"}
omitempty
这时候可以把这个字段定义成对应的指针类型,如下面结构体Person3的Addr字段
type Person3 struct {
Name string `json:"name"`
Age int `json:"age"`
Addr *string `json:"addr,omitempty"`
}
虽然json对象不管有没有"addr"这个键,得到的Person3对象都能够访问Addr字段,但可以通过比较Addr是否等于nil来判断json对象存不存在对应键,如果等于nil 则说明不存在,反之则存在。这里其实是利用了指针的零值为nil的特性。
添加omitempty的时机
对于一个指针类型的字段,无论是否添加omitempty字段,在不给该字段传值的情况,默认会被赋予一个空指针,依旧可以对这个结构体对象的该字段判断是否为空
其实就是对于一个结构体的字段而言,是否添加该字段只会影响到该结构体对象转化为json对象,添加了该字段,而恰好创建这个结构体对象时这个字段又没有传入值,那这个字段就会默认被赋予一个零值,然后再转换为json对象的时候这个字段就会被省略掉,使得展开jso对象的时候是看不到这个字段的。但并不会影响到这个结构体对象的使用,结构体的这个字段就是一个零值,类比的你可以想象创建一个空结构体对象的时候,那么所有字段都初始化为对应类型的零值了
int*int*string(指针)
type Book struct {
Name string `json:"name"`
Price float32 `json:"price"`
Desc string `json:"desc,omltempty"`
Author //匿名结构体
}
type Book2 struct {
Name string `json:"name"`
Price float32 `json:"price"`
Desc string `json:"desc,omitempty"`
Author Author `json:"author,omitempty"` //有名结构体
}
type Book3 struct {
Name string `json:"name"`
Price float32 `json:"price"`
Desc string `json:"desc,omitempty"`
Author *Author `json:"author,omitempty"` //有名结构体(指针类型)
}
type Author struct {
Gender int `json:"gender,omitempty"`
Age int `json:"age,Omitempty"`
}
1)匿名结构体本质上更接近外层结构体的字段的一个集合,并不算结构体嵌套。
func main() {
var book Book
book.Name = "testBook"
bookByte, _ := json.Marshal(book)
fmt.Printf("%s\n", string (bookByte))
}
对于上面的定义,在Gender和Age都没有赋值的情况下,输出的结果下面这样,但要注意的是,被忽略掉其实是"gender"和"age'"两个键而非"author"这个键,只要给Gender或者Age字段赋值,"gender"或"age"键就会显示出来,且和"name"、"price" 平级。
{"name":"testBook","price":0}
2)而有名结构体依旧可以按照两种方式去讨论,即原类型和指针类型
func main() {
var book Book
book.Name = "testBook"
bookByte, _ := json.Marshal(book)
fmt.Printf("%s\n", string (bookByte))
}
比如原类型结果是这样
{"name":"testBook","price":0,"author":{}}
但指针类型的结果就会忽略掉"author"键
{"name":"testBook","price":0}
*ptr
总结来说就是下面几点
1)结构体转json时,如果希望某个字段不显式初始化(赋值)就不会存在对应的键,则加上0mitempty关键字
2)如果已经加上了omitempty关键字,但显示初始化(赋值)这个字段的数据又可能为该类型的零值,则需要考虑将这个字段转成对应的指针类型去处理,否则这 个字段即便传入了值,最后仍然会因为是零值而被忽略
3) json转结构体时,某个字段的值是零值(如int类型的字段数值为0),如果需要确定json对象是否存在这样一个键,则可以将这个字段转成对应的指针类型去处理