【go从零单排】JSON序列化和反序列化

🌈Don't worry , just coding!
内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。

📗概念

在 Go 语言中,处理 JSON 数据主要依赖于 encoding/json 包。这个包提供了编码(序列化)和解码(反序列化)JSON 数据的功能。

💻代码

Example

go 复制代码
package main

//导入了 encoding/json(用于处理 JSON 数据)、fmt(用于格式化输出)和 os(用于操作系统功能)包。
import (
	"encoding/json"
	"fmt"
	"os"
)

// 定义了两个结构体 response1 和 response2。
// response2 使用了结构体标签(tags),指定了 JSON 字段名,这样在序列化时可以控制字段名称
type response1 struct {
	Page   int//首字母必须大写才能导出字段
	Fruits []string
}

type response2 struct {
	Page   int      `json:"page"`
	Fruits []string `json:"fruits"`
}

func main() {
	//使用 json.Marshal 将其转换为 JSON 格式的字节切片,并转为字符串输出。
	bolB, _ := json.Marshal(true)
	fmt.Println(string(bolB)) // 输出: true

	intB, _ := json.Marshal(1)
	fmt.Println(string(intB)) // 输出: 1

	fltB, _ := json.Marshal(2.34)
	fmt.Println(string(fltB)) // 输出: 2.34

	strB, _ := json.Marshal("gopher")
	fmt.Println(string(strB)) // 输出: "gopher"

	slcD := []string{"apple", "peach", "pear"}
	slcB, _ := json.Marshal(slcD)
	fmt.Println(string(slcB)) // 输出: ["apple","peach","pear"]

	mapD := map[string]int{"apple": 5, "lettuce": 7}
	mapB, _ := json.Marshal(mapD)
	fmt.Println(string(mapB)) // 输出: {"apple":5,"lettuce":7}

	res1D := &response1{
		Page:   1,
		Fruits: []string{"apple", "peach", "pear"}}
	res1B, _ := json.Marshal(res1D)
	fmt.Println(string(res1B)) // 输出: {"Page":1,"Fruits":["apple","peach","pear"]}

	res2D := &response2{
		Page:   1,
		Fruits: []string{"apple", "peach", "pear"}}
	res2B, _ := json.Marshal(res2D)
	fmt.Println(string(res2B)) // 输出: {"page":1,"fruits":["apple","peach","pear"]}

	byt := []byte(`{"num":6.13,"strs":["a","b"]}`)

	var dat map[string]interface{}

	if err := json.Unmarshal(byt, &dat); err != nil {
		panic(err)
	}
	fmt.Println(dat) // 输出: map[num:6.13 strs:[a b]]

	num := dat["num"].(float64)//num是float的类型,这里需要手动转化
	fmt.Println(num)

	strs := dat["strs"].([]interface{})
	str1 := strs[0].(string)
	fmt.Println(str1)

	str := `{"page": 1, "fruits": ["apple", "peach"]}`
	res := response2{}
	//[]byte(str) 将 JSON 字符串 str 转换为字节切片,以便 Unmarshal 函数可以处理。
	//&res 是一个指向 res 的指针,表示解码后的数据将存储在 res 中。
	json.Unmarshal([]byte(str), &res)
	fmt.Println(res)           // 输出: {1 [apple peach]}
	fmt.Println(res.Fruits[0]) // 输出: apple
	//使用 json.NewEncoder 创建一个 JSON 编码器,将数据直接编码到标准输出流(os.Stdout)。
	enc := json.NewEncoder(os.Stdout)
	d := map[string]int{"apple": 5, "lettuce": 7}
	enc.Encode(d) // 输出: {"apple":5,"lettuce":7}
}

//输出
//true
//1
//2.34
//"gopher"
//["apple","peach","pear"]
//{"apple":5,"lettuce":7}
//{"Page":1,"Fruits":["apple","peach","pear"]}
//{"page":1,"fruits":["apple","peach","pear"]}
//map[num:6.13 strs:[a b]]
//6.13
//a
//{1 [apple peach]}
//apple
//{"apple":5,"lettuce":7}

序列化

将 Go 数据结构转换为 JSON 格式的字符串。

go 复制代码
package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    // 示例数据
    data := map[string]interface{}{
        "name": "Alice",
        "age":  30,
        "hobbies": []string{"reading", "traveling"},
    }

    // 编码为 JSON
    jsonData, err := json.Marshal(data)
    if err != nil {
        fmt.Println("Error encoding JSON:", err)
        return
    }
    fmt.Println(string(jsonData)) // 输出: {"age":30,"hobbies":["reading","traveling"],"name":"Alice"}
}

反序列化

将 JSON 格式的字符串转换为 Go 数据结构。

go 复制代码
package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    jsonStr := `{"name": "Alice", "age": 30, "hobbies": ["reading", "traveling"]}`

    var data map[string]interface{}

    // 解码 JSON
    err := json.Unmarshal([]byte(jsonStr), &data)
    if err != nil {
        fmt.Println("Error decoding JSON:", err)
        return
    }
    fmt.Println(data) // 输出: map[age:30 hobbies:[reading traveling] name:Alice]
}

切片序列化

Go 的切片可以直接映射到 JSON 数组。

go 复制代码
func main() {
    fruits := []string{"apple", "banana", "cherry"}
    
    jsonData, err := json.Marshal(fruits)
    if err != nil {
        fmt.Println("Error encoding JSON:", err)
        return
    }
    fmt.Println(string(jsonData)) // 输出: ["apple","banana","cherry"]
}

使用 JSON 标签

通过结构体标签自定义 JSON 字段名。

go 复制代码
type Person struct {
    Name    string   `json:"name"`
    Age     int      `json:"age"`
    Hobbies []string `json:"hobbies"`
}

序列化结构体

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)
//定义结构体
type Person struct {
	Name    string   `json:"name"`
	Age     int      `json:"age"`
	Hobbies []string `json:"hobbies"`
}

func main() {
	person := Person{
		Name:    "Alice",
		Age:     30,
		Hobbies: []string{"reading", "traveling"},
	}
	//序列化结构体
	jsonData, err := json.Marshal(person)
	if err != nil {
		fmt.Println("Error encoding JSON:", err)
		return
	}
	fmt.Println(string(jsonData)) // 输出: {"age":30,"hobbies":["reading","traveling"],"name":"Alice"}
}

反序列化结构体

go 复制代码
func main() {
    jsonStr := `{"name": "Alice", "age": 30, "hobbies": ["reading", "traveling"]}`
    
    var person Person
    //[]byte(jsonStr) 将一个字符串(jsonStr)转换为字节切片。这是因为 json.Unmarshal 需要一个字节切片作为输入参数,而不是字符串。
    err := json.Unmarshal([]byte(jsonStr), &person)
    if err != nil {
        fmt.Println("Error decoding JSON:", err)
        return
    }
    fmt.Println(person) // 输出: {Alice 30 [reading traveling]}
}
  • 在 Go 中,json.Unmarshal 函数用于将 JSON 格式的字节切片解码为 Go 数据结构。这里的 []byte 是一个字节切片类型,表示 JSON 数据的原始字节序列。
  • 字节切片:[]byte 是 Go 中的一个基本数据类型,表示一个字节的动态数组。每个字节是一个 8 位的无符号整数,通常用于表示原始数据,如文本、二进制数据等。
  • JSON 字符串:在 JSON 数据的上下文中,JSON 字符串通常是以 UTF-8 编码的文本。要将 JSON 字符串转换为 Go 数据结构,首先需要将其转换为字节切片。

🔍理解

  • 序列化是把go的数据结构转为json格式,用json.Marshal(data)
  • 反序列化是把json格式转为go的数据格式,用json.Unmarshal

💡 Tips小知识点

错误处理

在编码和解码过程中,建议检查错误,以确保数据的正确性。

go 复制代码
if err != nil {
    fmt.Println("Error:", err)
}

JSON 编码到输出流

使用 json.Encoder 将 JSON 数据直接写入到输出流(如标准输出)。

go 复制代码
enc := json.NewEncoder(os.Stdout)
data := map[string]int{"apple": 5, "banana": 2}
enc.Encode(data) // 输出: {"apple":5,"banana":2}

💪无人扶我青云志,我自踏雪至山巅。

相关推荐
花酒锄作田3 天前
Gin 框架中的规范响应格式设计与实现
golang·gin
qwfys2003 天前
How to install golang 1.26.0 to Ubuntu 24.04
ubuntu·golang·install
codeejun3 天前
每日一Go-25、Go语言进阶:深入并发模式1
开发语言·后端·golang
石牌桥网管3 天前
Go 泛型(Generics)
服务器·开发语言·golang
上海合宙LuatOS3 天前
LuatOS核心库API——【json 】json 生成和解析库
java·前端·网络·单片机·嵌入式硬件·物联网·json
敲代码的柯基3 天前
一篇文章理解tsconfig.json和vue.config.js
javascript·vue.js·json
小二·3 天前
Go 语言系统编程与云原生开发实战(第21篇)
开发语言·云原生·golang
小二·3 天前
Go 语言系统编程与云原生开发实战(第20篇)
开发语言·云原生·golang
女王大人万岁3 天前
Golang实战Eclipse Paho MQTT库:MQTT通信全解析
服务器·开发语言·后端·golang
codeejun3 天前
每日一Go-24、Go语言实战-综合项目:规划与搭建
开发语言·后端·golang