1.结构体和Json
成员变量名必须要大写字母开头,否则解析失败
json字符串转对象的时候,可以不区分大小写,如以下 {"uniqueid":"123", "no":"500"}都可以成功Unmarshal
go中根据首字母的大小写来确定可以访问的权限。无论是方法名、常量、变量名还是结构体的名称,如果首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用
type CurrUser struct{
Name string `json:"name,omitempty"` //如果为空值,则转json的时候,该字段不生成,从没有该字段的json字符串转结构体的时候,不报错,为默认值
No int `json:"no,omitempty"`
Uniqueid string `json:"uniqueid,omitempty"`
}
结构体中的成员变量是byte切片的时候,生成的json会自动进行base64编码,解析的时候,反过来也同理
Message := DataMessage{Body:[]byte("xiaoyu你好!")}
str, _ := json.Marshal(&Message)
// fmt.Printf("BagItemSub Message %s", string(str))
// decodeBytes, _ := base64.StdEncoding.DecodeString("eGlhb3l15L2g5aW977yB")
// fmt.Println(string(decodeBytes))
//strJson := "{\"body\" : \"你好!\"}"
strJson := string(str)
msg := DataMessage{}
json.Unmarshal([]byte(strJson), &msg)
结构体只要包含json字符串中部分需要解析的成员就可以了,不需要使用的字段可以不写在结构体的成员变量中
结构体中嵌套的结构体,可以是指针
type InStr struct {
Age int64 `json:"age,omitempty"`
}type TestStruct struct {
Name string `json:"name,omitempty"`
ID int32 `json:"id,omitempty"`
MyAge *InStr `json:"myage,omitempty"`
No *int64 `json:"no,omitempty"`
}inStr := InStr{Age: 20}
iNo := int64(110)
testStruct := TestStruct{Name: "xiaoyu",
ID: 16,
MyAge: &inStr,
No: &iNo}
fmt.Println(testStruct)
byteJson, _ := json.Marshal(testStruct)
fmt.Println(string(byteJson))生成嵌套json:
{"name":"xiaoyu","id":16,"myage":{"age":20},"no":110}
结构体成员如果是枚举类型,最终生成的json值也是 数值类型,比如赋值TeamType_DISCUZ,实际值为1
type TeamType int32
const (
TeamType_GROUP TeamType = 0
TeamType_DISCUZ TeamType = 1
TeamType_CHATROOM TeamType = 2
)type Team struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
HeadImg string `protobuf:"bytes,3,opt,name=head_img,json=headImg" json:"head_img,omitempty"`
Type TeamType `protobuf:"varint,4,opt,name=type,enum=com.sencent.im.model.TeamType" json:"type,omitempty"`
Silenced bool `protobuf:"varint,5,opt,name=silenced" json:"silenced,omitempty"`
}
team := &Team{Id : "123", Type : TeamType_DISCUZ}
byteJson, _ := json.Marshal(team)
strJson := string(byteJson) "{"id":"123","type":1}"
结构体中嵌套不确定结构的结构体,使用接口就行了:
type Group struct {
Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
HeadImg string `protobuf:"bytes,3,opt,name=head_img,json=headImg" json:"head_img,omitempty"`
}
type Msg struct {
Info string `protobuf:"bytes,2,opt,name=info" json:"info,omitempty"`
}type ApiRsp struct{
ErrCode int64 `protobuf:"bytes,1,opt,name=err_code" json:"err_code,omitempty"`
Data interface{} `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"`
Msg interface{} `protobuf:"bytes,1,opt,name=msg" json:"msg,omitempty"`
}func main(){
group := Group{Name:"xiaoyu"}
msg := Msg{Info : "i don't konw"}
apiRsp := &ApiRsp{ErrCode : 1, Data : &group, Msg :&msg}
byteJson, _ := json.Marshal(apiRsp)
strJson := string(byteJson)
fmt.Println(strJson)
}
2.利用反射获得结构体的成员变量名
package main
import (
"fmt"
"reflect"
)type User struct{
UName string
}type resume struct {
Name string //`json:"name" doc:"我的名字"`
Sex string //`json:"name" doc:"我的名字"`
Age int
Tel string
SUser User
}//注意stru是接口,传递参数的时候是结构体指针
func findDoc(stru interface{}) map[string]string {
t := reflect.TypeOf(stru).Elem()
doc := make(map[string]string) for i := 0; i < t.NumField(); i++ {
//doc[t.Field(i).Tag.Get("json")] = t.Field(i).Tag.Get("doc")
fmt.Println(t.Field(i).Name)
} return doc
}
func main() {
stru := resume{}
doc := findDoc(&stru)
fmt.Printf("name字段为:%s\n", doc["name"])
}
2.接口
iValue := 100 //默认是int类型,要赋值给int32 /int64要进行类型转换
package main
import "fmt"
func main() {
var a interface{} //没有赋值(类型,实现任何接口)是nil类型
//a.(string) 会崩溃,空接口转其他类型会崩溃,使用ok进行判断
//var b string
//a = "asdasdasdasd"
//a = 32 int类型, 不同于int32/int64,不能直接转换
a = int32(32) //int64类型
switch a.(type){
case string:
fmt.Print("string\n")
case int:
fmt.Print("int\n")
case int32:
fmt.Print("int32\n")
case int64:
fmt.Print("int64\n")
case nil:
fmt.Print("nil\n")
}
if c, ok := a.(int32); ok{
fmt.Println(c)
}
value := a.(int64) //类型不对,会crash
fmt.Println(value)
}
运用案例:
解析的时候,要将Data 转为具体的对象数组(切片),不然解析不到对象,注意要使用&arrAccount指针
type ApiRsp struct{
ErrCode int64 `protobuf:"bytes,1,opt,name=error_code" json:"error_code"`
//如果Data为nil,则生成的json中Data的值为null,不雅观,所以赋值一个大小为0的切片
Data interface{} `protobuf:"bytes,1,opt,name=data" json:"data"` //, omitempty
Msg string `protobuf:"bytes,1,opt,name=message" json:"message"`
}func (apiRsp *ApiRsp)GetJsonString() string{
strJson, _ := json.Marshal(apiRsp)
return string(strJson)
}//data必须是数组,切片,对象指针或者nil,能够自动将obj转为[]
//{"err_code":0,"data":[数组],"msg":""}
func ApiHttpRsp(c *gin.Context, errCode int64, data interface{}, msg string ){
empData := make([]interface{}, 0) //避免Data :[NULL]
apiRsp := &ApiRsp{ErrCode : 0, Data : empData, Msg : ""}
apiRsp.ErrCode = errCode
apiRsp.Msg = msg
if (nil != data){
strType := reflect.TypeOf(data).Kind() //如果data是nil,.Kind()方法会报错
if (reflect.Ptr == strType){
empData = append(empData, data)
apiRsp.Data = empData
}else{
apiRsp.Data = data
}
}
strRsp := apiRsp.GetJsonString()
c.String(http.StatusOK, strRsp)
}//比如这样的json
{
"error_code": 0,
"data": [{
"id": "123456",
"token": "77888",
"token_gen_time": 1577413605,
}],
"message": ""
}
那要怎么解析呢成对象呢?比如有Account对象
type Account struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
Token string `protobuf:"bytes,3,opt,name=token" json:"token,omitempty"`
TokenGenTime int64 `protobuf:"varint,4,opt,name=token_gen_time,json=tokenGenTime" json:"token_gen_time,omitempty"`
} apiRsp := &ApiRsp{}
arrAccount := make([]*model.Account, 0)
apiRsp.Data = &arrAccount //解析的时候,要将Data 转为具体的对象数组(切片),不然解析不到对象,注意要使用&arrAccount指针。否则apiRsp.Data这个接口是切片类型,这样的转换失败apiRsp.Data.(*[]*model.Account)
log.Debug("%s rsp: %s", strPath, strRsp)
if err := json.Unmarshal([]byte(strRsp), &apiRsp); err != nil {
log.Error("loginRes Unmarshal error", err)
return
}
//g_account = arrAccount[0] //这是一种方法
arrData, ok := apiRsp.Data.(*[]*model.Account)
if ok{
g_account = (*arrData)[0] //这也是一种方法}
//strType := reflect.TypeOf(apiRsp.Data).String()
解析[{},{}]这样的数组json
var thresholdList []*Threshold
var err error = nil
err := json.Unmarshal([]byte(thresholds), &thresholdList)