json的序列化,反序列化以及应用

在 Go 语言中,json.Marshaljson.Unmarshal是用于处理 JSON 数据的两个关键函数。

它们的使用涉及到传递指针非指针类型的细微差别。

json.Marshal的序列化

json.Marshal函数将 Go 语言的值序列化为 JSON 字符串。在使用json.Marshal时,通常传递非指针类型即可。

  • 传值类型: 当你传递一个结构体、切片、映射、数组等类型时,json.Marshal 会自动将这些值序列化为 JSON。 示例:
type Person struct {
    Name string
    Age  int
}

person := Person{Name: "Alice", Age: 30}
jsonData, err := json.Marshal(person) // 传递值类型
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(jsonData))
// 输出: {"Name":"Alice","Age":30}
  • 传指针类型: 虽然可以传递指针类型给json.Marshal,但这不是必需的,因为 Go 会自动处理指针的解引用。也就是说,无论是值还是指针,结果都是相同的。 示例:
personPtr := &Person{Name: "Alice", Age: 30}
jsonData, err := json.Marshal(personPtr) // 传递指针类型
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(jsonData))
// 输出: {"Name":"Alice","Age":30}

json.Unmarshal的反序列化

json.Unmarshal函数用于将 JSON 字符串解析为 Go 语言的值。在使用 json.Unmarshal时,必须传递指针类型,以便函数能够修改目标对象。

  • 传指针类型: 因为json.Unmarshal需要将解析后的数据写入目标变量中,所以需要传递目标变量的指针。只有传递指针,json.Unmarshal才能修改目标变量的值。 示例:
jsonData := `{"Name":"Alice","Age":30}`
var person Person
err := json.Unmarshal([]byte(jsonData), &person) // 传递指针类型
if err != nil {
    log.Fatal(err)
}
fmt.Printf("%+v\n", person)
// 输出: {Name:Alice Age:30}
  • 不传指针会报错: 如果你不传递指针,而是传递一个值,json.Unmarshal将无法修改目标值,并且会报错。 示例:
var person Person
err := json.Unmarshal([]byte(jsonData), person) // 不传递指针会报错
if err != nil {
    log.Fatal(err) // 会在这里报错:json: Unmarshal(non-pointer main.Person)
}

json的序列化应用

这里我们主要介绍一下结构体、map 切片的序列化,其它数据类型的序列化与其类似。

package main

import (
	"fmt"
	"encoding/json"
)

//定义一个结构体
type Monster struct {
	Name string
	Age int
	Birthday string
	Sal float64
	Skill string
}

func testStruct() {
	monster := Monster{
		Name :"牛魔王", Age : 500,
		Birthday : "2011-11-11",
		Sal : 8000.0,
		Skill : "牛魔拳",
	}
	//将 monster 序列化
	data, err := json.Marshal(&monster)
	if err != nil {
		fmt.Printf("序列号错误 err=%v\n", err)
	}
	//输出序列化后的结果
	fmt.Printf("monster 序列化后=%v\n", string(data))
}
//将 map 进行序列化
func testMap() {
	//定义一个 map
	var a map[string]interface{}
	//使用 map,需要 make
	a = make(map[string]interface{})
    a["name"] = "红孩儿"
	a["age"] = 30
	a["address"] = "洪崖洞" 
	//将 a 这个 map 进行序列化
	//将 monster  序列化
	data, err := json.Marshal(a)
	if err != nil {
		fmt.Printf("序列化错误 err=%v\n", err)
	}
	//输出序列化后的结果
	fmt.Printf("a map 序列化后=%v\n", string(data))
}
//对切片进行序列化, 我们这个切片 []map[string]interface{}
func testSlice() {
	var slice []map[string]interface{}
	var m1 map[string]interface{}
	//使用 map 前,需要先 make
	m1 = make(map[string]interface{})
	m1["name"] = "jack"
	m1["age"] = "7"
	m1["address"] = "北京"
	slice = append(slice, m1)
	
	var m2 map[string]interface{}
	//使用 map 前,需要先 make
	m2 = make(map[string]interface{})
	m2["name"] = "tom"
	m2["age"] = "20"
	m2["address"] = [2]string{"墨西哥","夏威夷"}
	slice = append(slice, m2)
	
	//将切片进行序列化操作
	data, err := json.Marshal(slice)
	if err != nil {
		fmt.Printf("序列化错误 err=%v\n", err)
	}
	//输出序列化后的结果
	fmt.Printf("slice 序列化后=%v\n", string(data))
}

//对基本数据类型序列化,对基本数据类型进行序列化意义不大
func testFloat64() {
	var num1 float64 = 2345.67
	//对 num1 进行序列化
	data, err := json.Marshal(num1)
	if err != nil {
		fmt.Printf("序列化错误 err=%v\n", err)
	}
	//输出序列化后的结果
	fmt.Printf("num1 序列化后=%v\n", string(data))
}

func main() {
	//演示将结构体, map , 切片进行序列号
	testStruct()
	testMap()
	testSlice()//演示对切片的序列化
	testFloat64()//演示对基本数据类型的序列化
}

注意事项:对于结构体的序列化,如果我们希望序列化后的key 的名字,又我们自己重新制定,那么可以给struct指定一个 tag 标签。

json的反序列化应用

这里我们主要介绍一下将 json 字符串反序列化成结构体、map 和切片,其它数据类型的反序列化与其类似。

package main

import (
	"fmt"
	"encoding/json"
)

//定义一个结构体
type Monster struct {
	Name string
	Age int
	Birthday string
	Sal float64
	Skill string
}

//演示将 json 字符串,反序列化成 struct
func unmarshalStruct() {
	//说明 str 在项目开发中,是通过网络传输获取到..  或者是读取文件获取到
	str := "{\"Name\":\"牛魔王\",\"Age\":500,\"Birthday\":\"2011-11-11\",\"Sal\":8000,\"Skill\":\"牛魔拳\"}"

	//定义一个 Monster 实例
	var monster Monster
	err := json.Unmarshal([]byte(str), &monster)
	if err != nil {
		fmt.Printf("unmarshal err=%v\n", err)
	}
	fmt.Printf("反序列化后 monster=%v monster.Name=%v \n", monster, monster.Name)
}

//将 json 字符串,反序列化成 map
func unmarshalMap() {
	str := "{\"address\":\"洪崖洞\",\"age\":30,\"name\":\"红孩儿\"}"
	//定义一个 map
	var a map[string]interface{}
	//反序列化
	//注意:反序列化 map,不需要 make,因为 make 操作被封装到 Unmarshal 函数
	err := json.Unmarshal([]byte(str), &a)
	if err != nil {
		fmt.Printf("unmarshal err=%v\n", err)
	}
	fmt.Printf("反序列化后 a=%v\n", a)
}

//将 json 字符串,反序列化成切片
func unmarshalSlice() {
	str := "[{\"address\":\"北京\",\"age\":\"7\",\"name\":\"jack\"}," +
	"{\"address\":[\"墨西哥\",\"夏威夷\"],\"age\":\"20\",\"name\":\"tom\"}]"
	
	//定义一个 slice
	var slice []map[string]interface{}
	//反序列化,不需要 make,因为 make 操作被封装到 Unmarshal 函数
	err := json.Unmarshal([]byte(str), &slice)
	if err != nil {
		fmt.Printf("unmarshal err=%v\n", err)
	}
	fmt.Printf("反序列化后 slice=%v\n", slice)
}

func main() {
	unmarshalStruct()
	unmarshalMap()
	unmarshalSlice()
}

注意事项

  1. 在反序列化一个json 字符串时,要确保反序列化后的数据类型和原来序列化前的数据类型一致。

  2. 如果 json 字符串是通过程序获取到的,则不需要再对 转义处理。
     

总结

  • json.Marshal:既可以传递值也可以传递指针,一般情况下传递值即可。
  • json.Unmarshal: 必须传递指针,以便函数能够修改目标变量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值