初探go中序列化使用注意点(json篇)

JSON及序列化知识介绍

说到json,其实我们不得不说的是序列化,因为json就是序列化的一种协议。
序列化的目的是为了对象可以跨平台存储和进行网络传输,而网络传输是需要二进制字节这个形式的。那么在进行网络传输之前,就需要把对象转换成二进制字节,这个过程就是序列化的过程。
在使用方将对象转成二进制字节及接收方收到后将字节恢复的过程中,就需要两方规定好转换的规则,而这种规则就是所谓的协议。(说句题外话,之前看一种说法说盗墓笔记里面的胡八一为什么按照风水学可以找到大墓呢?是因为埋的人按照这套风水学埋的,所以盗墓的人按照这个来挖,自然就可以找得到。换到这里来说,埋的人用json这种规则来埋,你盗墓如果用Protobuf这种规则的话,自然是不成的)。
常见的序列化协议有json、xml、Protobuf、Thrift。之间区别等我再开一篇文章来说道说道。我们这次不谈屁股。

GO中JSON使用

一般来讲json串的反序列化都会解析成一个结构体,所以这里有一个区分是:一类是我实现知道会反序列化成什么样子的结构体,还有一类就是我事先不知道是什么样子的结构体,这一类会用在比较通用的地方:

明确结构体的json解析:

	    type exampleStruct struct {
			StartTime string `json:"startTime"`
			EndTime   string `json:"endTime"`
		}
		
		var exampleObject exampleStruct
		
		err := json.Unmarshal([]byte(jsonStr), &exampleObject)
		if err != nil {
		}
		

这个是我们比较常用的形式;

不确定结构体的json解析

这种在反序列化的时候,因为没有确定结构体,所以会以map[string]interface{}来充当结构体的角色。这个也很好理解,key-value形式一般key为string格式,而value则不确定。

exampleMap := make(map[string]interface{}, 0)
err := json.Unmarshal([]byte(jsonStr), &exampleMap)
err!=nil{
}

这种形式其实相对第一种比较不常用,使用的时候会在一些更通用或者说抽象的地方来使用。例如:在gin框架中,会观察到:
在这里插入图片描述

func (self *HttpServer) ping(context *gin.Context) {
	context.JSON(200, gin.H{
		"message": "pong",
	})
}

就是这样来使用的,在gin.H这里我们需要传入的是一个结构体,但是这个比较通用一点,为了适用大多情况,这里用一个map[string]interface{}的形式来代替一个具体的结构体。
这种序列化给我们带来了便利,但是在反序列化的时候,这种通用的形式使用起来就很难受,说到底它还是一个map,在我们使用map的时候需要判断key是否存在,同时这里的value是any形式,在使用的过程中就需要类型判定。

	value, ok := exampleMap["exampleKey"]; ok {
		valueR := value.(string)
	}

结构体json的Tag作用:

可以看到结构体中json是在序列化及反序列化中不可缺少的一大部分,这里是通过反射来实现字段和tag的绑定关系的,在接下来的浅析源码中会对这一部分进行深入的探寻。

结构体标签三个注意点:

1)结构体里面嵌套结构体
这种情况是,并不能保证在结构体里面的字段都是基础类型,结构体中包含结构体也是很常见的,这时候我们需要怎么定义呢?

type School struct {
	Name    string          `json:"name"`
	Address string          `json:"address"`
	Grade   json.RawMessage `json:"grade"`
}

type Grade struct {
	Class    string `json:"class"`
	Students string `json:"students"`
}

这时候我们就需要用到json.RawMessage这个类型了
请添加图片描述
其实json.RawMessage也没什么特别的也就是[]byte请添加图片描述

2)结构体中忽略不存在的

type School struct {
	Name     string `json:"name"`
	Address  string `json:"address"`
	Students string `json:"-"`
	privateFiled string `json:"privateFiled"`
}

func main() {
	jsonString := `{"name":"name","address":"shanghai","addFields":"321"}`

	var schoolExample School
	err := json.Unmarshal([]byte(jsonString), &schoolExample)

	if err != nil {
		fmt.Println(err.Error())
		return
	}

	s := School{
		Name:     "name",
		Address:  "address",
		Students: "students",
		privateFiled: "privateFiled",
	}

	sByte, err := json.Marshal(s)
	fmt.Println(string(sByte))
	//{"name":"name","address":"address"}

}

这种在json:"-"的形式,其实在反序列化的时候作用不大,在序列化的时候:这种保证了某些值不会被序列化传到外边去(起到一个数据保护的作用)

3)私有值
还有一点就是privateFiled这个字段,它的首字母是小写的证明了这个是一个一个私有变量,这个在序列化中其实和json:"-"的形式的作用没有差别。这里特别拉出来说是是为了给源码解析做个铺垫。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值