38.1 序列化与反序列化

序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。

我们的数据对象要在网络中传输或保存到文件,就需要对其编码和解码动作,目前存在很多编码格式:JSON,XML,Gob,Google Protocol Buffer等,Go 语言当然也支持所有这些编码格式。

序列化期间,对象将其当前状态写入到临时或持久性存储区。通过从存储区中读取对象的状态,重新创建该对象,则为反序列化。

简单地说把某种数据结构转为指定数据格式为“序列化”或“编码”(传输之前);而把“指定数据格式”转为某种数据结构则为“反序列化”或“解码”(传输之后)。

Go语言中,encoding/json标准包处理JSON数据的序列化与反序列化问题。

JSON数据序列化函数主要有:

//json.Marshal()
func Marshal(v interface{}) ([]byte, error) {
	e := newEncodeState()
	err := e.marshal(v, encOpts{escapeHTML: true})
	if err != nil {
		return nil, err
	}
	buf := append([]byte(nil), e.Bytes()...)
	e.Reset()
	encodeStatePool.Put(e)
	return buf, nil
}

从上面的Marshal()函数我们可以看到,数据结构序列化后返回的是字节数组,而字节数组很容易通过网络传输或写入文件存储。而且在Go中,Marshal()默认是设置escapeHTML = true的,会自动把 '', 以及 '&' 等转化为"\u003c" , "\u003e"以及 "\u0026"。

JSON数据反序列化函数主要有:

// UnMarshal()
func Unmarshal(data []byte, v interface{}) error // 把 JSON 解码为数据结构

从上面的UnMarshal()函数我们可以看到,反序列化是读取字节数组,进而解析为对应的数据结构。

注意:不是所有的数据都可以编码为 JSON 格式,只有验证通过的数据结构才能被编码:

  • JSON 对象只支持字符串类型的 key;要编码一个 Go map 类型,map 必须是 map[string]T(T是 JSON 包中支持的任何类型)
  • channel,复杂类型和函数类型不能被编码
  • 不支持循环数据结构;它将引起序列化进入一个无限循环
  • 指针可以被编码,实际上是对指针指向的值进行编码(或者指针是 nil)

而在Go中,JSON 与 Go 类型对应如下:

  • bool 对应 JSON 的 booleans
  • float64 对应 JSON 的 numbers
  • string 对应 JSON 的 strings
  • nil 对应 JSON 的 null

在解析 JSON 格式数据时,若以 interface{} 接收数据,需要按照以上规则进行解析。

下一节:在Go语言中,利用encoding/json标准包将数据序列化为JSON数据格式这个过程简单直接,直接使用json.Marshal(v)来处理任意类型,序列化成功后得到一个字节数组。