Go语言基础: JSON序列化

JSON 是一种轻量级的数据交换格式。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

首先得熟悉结构体:

package main

import "fmt"

type Student struct {
	ID     int
	Gender string
	Name   string
	Sno    string
}

func main() {
	var s = Student{
		ID:     12,
		Gender: "男",
		Name:   "李四",
		Sno:    "001",
	}
	fmt.Printf("%#v\n", s)
}

如上代码中定义了一个结构体并且打印

结果: main.Student{ID:12, Gender:"男", Name:"李四", Sno:"001"}

转化为JSON字符串

package main

import (
	"encoding/json"
	"fmt"
)

type Student struct {
	ID     int
	Gender string
	Name   string
	Sno    string
}

func main() {
	var s = Student{
		ID:     12,
		Gender: "男",
		Name:   "李四",
		Sno:    "001",
	}
	// fmt.Printf("%#v\n", s)
	jsonbByte, _ := json.Marshal(s)
	jsonStr := string(jsonbByte)
	fmt.Println(jsonStr)
}

json.Marshal返回的是一个Byte类型的切片:

package json // import "encoding/json"

func Marshal(v any) ([]byte, error)
    Marshal returns the JSON encoding of v.

然后用string将其转为字符串并打印

那么JSON字符串也可以转化为结构体

package main

import (
	"encoding/json"
	"fmt"
)

type Student struct {
	ID     int
	Gender string
	Name   string
	Sno    string
}

func main() {
    // 使用反引号就无须转义字符
	var str = `{"ID":12,"Gender":"男","Name":"李四","Sno":"001"}`
	var s Student
	err := json.Unmarshal([]byte(str), &s)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("%#v", s)
}

这里用到Unmarshal函数来转换JSON字符串

package json // import "encoding/json"

func Unmarshal(data []byte, v any) error
    Unmarshal parses the JSON-encoded data and stores the result in the value
    pointed to by v. If v is nil or not a pointer, Unmarshal returns an
    InvalidUnmarshalError.

代码中Unmarshal函数接收两个参数,第一个是字节类型的切片,第二个是结构体变量地址。

要注意的是,如果结构体中的某字段的首字母是小写的,那么是不能转化为JSON字符串的,因为是该字段是私有的。

可以利用结构体标签来更改JSON字符串中的key的形式

package main

import (
	"encoding/json"
	"fmt"
)

type Student struct {
	ID     int    `json:"id"`     // 添加了结构体标签
	Gender string `json:"gender"`
	Name   string `json:"name"`
	Sno    string `json:"sno"`
}

func main() {
	var s = Student{
		ID:     12,
		Gender: "男",
		Name:   "李四",
		Sno:    "001",
	}
	// fmt.Printf("%#v\n", s)
	jsonbByte, _ := json.Marshal(s)
	jsonStr := string(jsonbByte)
	fmt.Println(jsonStr)
}

打印结果: {"id":12,"gender":"男","name":"李四","sno":"001"}

显然这个形式已经与之前的不一样了,首字母已经被改成了小写,这就是结构体标签作用之一。
下面是嵌套结构体的转化

package main

import (
	"encoding/json"
	"fmt"
)

// Student 学生结构体
type Student struct {
	ID     int    `json:"id"`
	Gender string `json:"gender"`
	Name   string `json:"name"`
	Sno    string `json:"sno"`
}

// Class 班级结构体
type Class struct {
	Title    string
	Students []Student
}

func main() {
	c := Class{
		Title:    "001 Class",
		Students: make([]Student, 0), // make创建切片
	}
	for i := 1; i < 10; i++ {
		s := Student{
			ID:     i,
			Gender: "男",
			Name:   fmt.Sprintf("stu_%v", i),
		}
		c.Students = append(c.Students, s) // 加入切片
	}
	fmt.Println(c)

	strByte, err := json.Marshal(c)
	if err != nil {
		fmt.Println(err)
	} else {
		strJson := string(strByte)
		fmt.Println(strJson)
	}
}

打印结果

{001 Class [{1 男 stu_1 } {2 男 stu_2 } {3 男 stu_3 } {4 男 stu_4 } {5 男 stu_5 } {6 男 stu_6 } {7 男 stu_7 } {8 男 stu_8 } {9 男 stu_9 }]}
{"Title":"001 Class","Students":[{"id":1,"gender":"男","name":"stu_1","sno":""},{"id":2,"gender":"男","name":"stu_2","sno":""},{"id":3,"gender":"男","name":"stu_3","sno":""},{"id":4,"gender":"男","name":_4","sno":""},{"id":5,"gender":"男","name":"stu_5","sno":""},{"id":6,"gender":"男","name":"stu_6","sno":""},{"id":7,"gender":"男","name":"stu_7","sno":""},{"id":8,"gender":"男","name":"stu_8","sno":""},{:9,"gender":"男","name":"stu_9","sno":""}]}

第一行是结构体信息,其后才是JSON数据

在这个JSON中是数据嵌套存放的,看着比较乱,可以借助 JSON在线解析 解析该数据

解析结果:

{
    "Title":"001 Class",
    "Students":[
        {
            "id":1,
            "gender":"男",
            "name":"stu_1",
            "sno":""
        },
        {
            "id":2,
            "gender":"男",
            "name":"stu_2",
            "sno":""
        },
        {
            "id":3,
            "gender":"男",
            "name":"stu_3",
            "sno":""
        },
        {
            "id":4,
            "gender":"男",
            "name":"stu_4",
            "sno":""
        },
        {
            "id":5,
            "gender":"男",
            "name":"stu_5",
            "sno":""
        },
        {
            "id":6,
            "gender":"男",
            "name":"stu_6",
            "sno":""
        },
        {
            "id":7,
            "gender":"男",
            "name":"stu_7",
            "sno":""
        },
        {
            "id":8,
            "gender":"男",
            "name":"stu_8",
            "sno":""
        },
        {
            "id":9,
            "gender":"男",
            "name":"stu_9",
            "sno":""
        }
    ]
}

那么又如何将这个字符串再转化回去?

如下所示

package main

import (
	"encoding/json"
	"fmt"
)

// Student 学生结构体
type Student struct {
	ID     int    `json:"id"`
	Gender string `json:"gender"`
	Name   string `json:"name"`
	Sno    string `json:"sno"`
}

// Class 班级结构体
type Class struct {
	Title    string
	Students []Student
}

func main() {
	str := `{"Title":"001 Class","Students":[{"id":1,"gender":"男","name":"stu_1","sno":""},{"id":2,"gender":"男","name":"stu_2","sno":""},{"id":3,"gender":"男","name":"stu_3","sno":""},{"id":4,"gender":"男","name":"stu_4","sno":""},{"id":5,"gender":"男","name":"stu_5","sno":""},{"id":6,"gender":"男","name":"stu_6","sno":""},{"id":7,"gender":"男","name":"stu_7","sno":""},{"id":8,"gender":"男","name":"stu_8","sno":""},{"id":9,"gender":"男","name":"stu_9","sno":""}]}`
	var c = &Class{} // 地址
	err := json.Unmarshal([]byte(str), c)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("%#v", *c)
}

打印结果

main.Class{Title:"001 Class", Students:[]main.Student{main.Student{ID:1, Gender:"男", Name:"stu_1", Sno:""}, main.Student{ID:2, Gender:"男", Name:"stu_2", Sno:""}, main.Student{ID:3, Gender:"男", Name:"stu_3", Sno:""}, main.Student{ID:4, Gender:"男", Name:"stu_4", Sno:""}, main.Student{ID:5, Gender:"男", Name:"stu_5", Sno:""}, main.Student{ID:6, Gender:"男", Name:"stu_6", Sno:""}, main.Student{ID:7, Gender:"男", Name:"stu_7", Sno:""}, main.Student{ID:8, Gender:"男", Name:"stu_8", Sno:""}, main.Student{ID:9, Gender:"男", Name:"stu_9", Sno:""}}}

JSON序列化就是将结构体转化为JSON字符串

JSON反序列化就是将JSON字符串转化为结构体

posted @ 2022-05-08 13:15  N3ptune  阅读(194)  评论(0编辑  收藏  举报