Go中的序列化和反序列化

1,663 阅读3分钟

这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战

序列化和反序列化

序列化: 把某种数据结构转换为指定的数据格式, 称为序列化或编码

反序列化: 把指定的数据格式转换为某种数据结构, 称为反序列化或解码

json中的key只能是字符串类型, 而value可以是布尔类型, 整型, 浮点型, 字符串, 结构体, 指针.

定义项目中用到的struct

我们只有只写了对应字段的标签, 才可以对结构体中的数据进行序列化和反序列化

 type Student struct {
    Name string `json:"name", xml:"name"`
    Age int `json:"age", xml:"age"`
    Master Teacher `json:"master", xml:"master"`
    Lesson
 }
 ​
 type Teacher struct {
    Name string `json:"name", xml:"name"`
    Age int `json:"age", xml:"age"`
 }
 ​
 type Lesson struct {
    Lessons []string `json:"lessons", xml:"lessons"`
 }

json的序列化 - MarshalIndent

其中v代表某种数据类型的变量, prefix每行的前缀, 传空字符串就可以了"", indent代表每行的缩进, 一般使用tab字符串, 返回参数为字节数组

 func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
 // 创建一个Student实例
 stu := Student{
    Name: "shaosiming",
    Age: 18,
    Master: Teacher{Name: "eastyellow", Age: 1000},
    Lesson: Lesson{Lessons: []string{"English", "Math"}},
 }
 ​
 // 使用带缩进的序列化方式
 data, err := json.MarshalIndent(stu, "", " ")
 if err != nil {
    fmt.Println("json marshal failed: ", err)
    return
 }
 fmt.Println(string(data))
 ​
 // 将字节流写入指定文件
 err = ioutil.WriteFile("stu.json", data, 0644)
 if err != nil {
    fmt.Println("write file failed: ", err)
    return
 }
 fmt.Println("write file succeed!")

json的反序列化 - Unmarshal

反序列化是将字节流转换为对应的数据结构

 func Unmarshal(data []byte, v interface{}) error
 // 从文件中读取json数据
 data, err := ioutil.ReadFile("./stu.json")
 if err != nil {
    fmt.Println("read file failed: ", err)
    return
 }
 ​
 // 创建一个空Student实例变量
 stu := &Student{}
 ​
 // 通过调用json.Unmarshal方法, 将字节流反序列化, 将数据赋值给stu
 err = json.Unmarshal(data, stu)
 if err != nil {
    fmt.Println("student json Unmarshal failed: ", err)
    return
 }
 fmt.Println("stu: ", stu)

json的Encode

将一个结构体实例经过编码写入到一个文件中进行存储

 // 创建一个student实例
 stu := &Student{
    Name: "shaosiming",
    Age: 18,
    Master: Teacher{Name: "eastyellow", Age: 1000},
    Lesson: Lesson{Lessons: []string{"English", "Math"}},
 }
 ​
 // 打开一个文件, 权限为只写和写入时清空文本
 fo, err := os.OpenFile("./x.json", os.O_WRONLY | os.O_TRUNC, 0644)
 if err != nil {
    fmt.Println("os create failed: ", err)
    return
 }
 fmt.Println("os create succeed!")
 ​
 // 使用json.NewEncoder解码器来将stu序列化到x.json文件中
 err = json.NewEncoder(fo).Encode(&stu)
 if err != nil {
    fmt.Println("json encode failed: ", err)
    return
 }
 fmt.Println("json encode succeed!")

json的Decode

从一个文件中读取字节流, 通过解码的方式从字节流中读取数据, 并将数据赋值到对应数据结构的实例

 // 创建一个空的Student类型的实例
 stu := &Student{}
 ​
 // 以只读的方式打开文件
 fo, err := os.OpenFile("./x.json", os.O_RDONLY, 0644)
 if err != nil {
    fmt.Println("open file failed: ", err)
    return
 }
 ​
 // 使用jsonr的Decoder将文件中的内容反序列化数据到stu中
 err = json.NewDecoder(fo).Decode(stu)
 if err != nil {
    fmt.Println("json encode failed: ", err)
    return
 }
 fmt.Println("json encode succeed!")
 fmt.Println(stu)

xml的序列化 - MarshalIndent

将一个结构体实例通过序列化转换为字节流, 再将字节流写入文件中进行存储

 // 创建一个Student类型的实例
 stu := &Student{
    Name: "shaosiming",
    Age: 18,
    Master: Teacher{Name: "eastyellow", Age: 1000},
    Lesson: Lesson{Lessons: []string{"English", "Math"}},
 }
 ​
 // 以带缩进的样式将stu实例序列化为字节流
 data, err := xml.MarshalIndent(stu, "", "  ")
 if err != nil {
    fmt.Println("xml marshal failed: ", err)
    return
 }
 fmt.Println(string(data))
 ​
 // 将字节流写入文件sut.xml中
 err = ioutil.WriteFile("stu.xml", data, 0644)
 if err != nil {
    fmt.Println(" write file failed: ", err)
    return
 }

xml的反序列化

从一个文件中读取字节流, 然后通过反序列化的方式将字节流转换成对应数据结构的数据

// 创建一个空的Student实例
stu := &Student{}

// 读取文件中的数据
data, err := ioutil.ReadFile("./stu.xml")
if err != nil {
   fmt.Println("read file failed: ", err)
   return
}

// 将读取到的字节流反序列化数据到stu中
err = xml.Unmarshal(data, stu)
if err != nil {
   fmt.Println("xml unmarshal failed: ", err)
   return
}

fmt.Println(stu)