Golang文件操作续-json

josn

1.JOSN基本介绍

json(JavaScript Object Notation)是一种轻量级的数据交换格式。易于人阅读和编写,经典的使用方式采取key-val形式来描述信息。
JSON易于机器解析和生成,并有效地提升网络传输效率,通常程序在网络传输时会先将数据(结构体、map等)序列化为json字符串;接收方得到json字符串后,在反序列化恢复成原来的数据类型(结构体、map等)。这种方式已然成为各个语言的标准。

json应用场景示意图这里是引用

2.json数据格式说明

在JS语言中,一切变量/实例都可以是对象。因此,任何数据类型都可以通过JSON来表示,例如字符串、数字、数组、结构体、map等。
JOSN是采用
键值对
来保存信息,其十分灵活、扩展性高。例如:

  1. 表示一个变量,具有单一信息:{"key1":val1}
    例如:{"Name":"Josn"}
  2. 表示一个变量具有多信息:{"key1":val1,"key2":val2,"key3":["val3_1","val3_2"]}
    例如:{"Name":"Josn","age":18,"add":["上海","北京"]}
  3. josn描述多个变量:[{...},{...}]格式
    例如:[{"Name":"Josn","age":18,"add":["上海","北京"]},{"Name":"Tom","age":18,"add":["武汉","成都"]}]

3.json数据在线解析

https://www.json.cn/网站可以验证一个json格式的数据是否正确。尤其是在编写比较复杂的json格式数据时,很有用。
在这里插入图片描述

4.json序列化

json序列化是指,将有key-value结构的数据类型(比如结构体、map、切片)序列化成json字符串的操作。

应用案例:
介绍结构体、map、切片的序列化,其它数据类型的序列化类似。
使用到encoding/json包中的func Marshal()函数

func Marshal(v interface{}) ([]byte, error)

案例演示:

type Person struct {
	Name     string
	Age      int
	Birthday string
	Salary   float64
}

// 结构体序列化
func (p *Person) testStruct() {
	data, err := json.Marshal(p)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("person 序列化后=%v\n", string(data))
}

// map序列化
func testMap() {
	m := make(map[string]interface{})
	m["Name"] = "红孩儿"
	m["age"] = 1500
	m["address"] = [2]string{"火云洞", "火焰山"}
	data, err := json.Marshal(m)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("map 序列化后=%v\n", string(data))
}

//切片序列化
func testSlice() {
	slice := make([]map[string]interface{}, 2)
	slice[0] = make(map[string]interface{})
	slice[0]["Name"] = [2]string{"孙悟空", "斗战胜佛"}
	slice[0]["Age"] = "5200"

	slice[1] = make(map[string]interface{})
	slice[1]["Name"] = "猪八戒"
	slice[1]["address"] = [2]string{"高老庄", "西天"}

	data, err := json.Marshal(slice)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("slice 序列化后=%v\n", string(data))
}
// 基本类型序列化
// 输出转为一个字符串,没特别意义
func testFloat64() {
	f := 12.13
	data, err := json.Marshal(f)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("float64 序列化后=%v\n", string(data))

}

func main() {
	person := Person{
		Name:     "Tom",
		Age:      18,
		Birthday: "2003-09-08",
		Salary:   5000,
	}
	person.testStruct()
	testMap()
	testSlice()
	testFloat64()
}

Output
person 序列化后={“Name”:“Tom”,“Age”:18,“Birthday”:“2003-09-08”,“Salary”:5000}
map 序列化后={“Name”:“红孩儿”,“address”:[“火云洞”,“火焰山”],“age”:1500}
slice 序列化后=[{“Age”:“5200”,“Name”:[“孙悟空”,“斗战胜佛”]},{“Name”:“猪八戒”,“address”:[“高老庄”,“西天”]}]
float64 序列化后=12.13


json字符串传输时往往接收端希望获得的key键值为小写或自定义,所以可以使用tag标签形式进行处理。
案例:

type Person struct {
	// 字段在json里的键为"name"且如果字段为空值将在对象中省略掉
	Name string `json:"name,omitempty"`
	// 字段在json里的键为"personAge"
	Age int `json:"personAge"`
	// 字段在json里的键为"Field"(默认值),但如果字段为空值会跳过;注意前导的逗号
	Birthday string `json:",omitempty"`
	// 字段被本包忽略
	Salary float64 `json:"-"`
}

// 结构体序列化
func (p *Person) testStruct() {
	data, err := json.Marshal(p)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("person 序列化后=%v\n", string(data))
}
func main() {
	person := Person{
		Name:     "Tom",
		Age:      18,
		Birthday: "2003-09-08",
		Salary:   5000,
	}
	person.testStruct()
}	

Output:
person 序列化后={“name”:“Tom”,“personAge”:18,“Birthday”:“2003-09-08”}


5.json反序列化

json反序列化即:将json字符串反序列成对应的数据类型(比如结构体、map、切片等)的操作。
代码演示:

package main
import (
	"encoding/json"
	"fmt"
	"log"
)

//将json字符串反序化成struct(在web中是没有结构体的)
type Person struct {
	// 字段在json里的键为"name"且如果字段为空值将在对象中省略掉
	Name string `json:"name,omitempty"`
	// 字段在json里的键为"personAge"
	Age int `json:"personAge"`
	// 字段在json里的键为"Field"(默认值),但如果字段为空值会跳过;注意前导的逗号
	Birthday string `json:",omitempty"`
	// 字段被本包忽略
	Salary float64 `json:"-"`
}

func (p *Person) unMarshalStruct(b []byte) {
	err := json.Unmarshal(b, p)
	if err != nil {
		log.Fatal(err)
	}
}

// 反序列化成map
func unMarshalMap() {
	jsonBlob := []byte(`{"Name":"红孩儿","address":["火云洞","火焰山"],"age":1500}`)
	var m map[string]interface{}
	// 在返序列化map,不需要make,因为make操作封装到了Unmarshal函数中
	//因此在参数列表中,即使m变量是应用类型,也需要加上&地址符,否则会报non-pointer
	err := json.Unmarshal(jsonBlob, &m)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("反序列化后map=%v\n", m)

}

//切片序列化
func testSlice() []byte {
	slice := make([]map[string]interface{}, 2)
	slice[0] = make(map[string]interface{})
	slice[0]["Name"] = [2]string{"孙悟空", "斗战胜佛"}
	slice[0]["Age"] = "5200"

	slice[1] = make(map[string]interface{})
	slice[1]["Name"] = "猪八戒"
	slice[1]["address"] = [2]string{"高老庄", "西天"}

	data, err := json.Marshal(slice)
	if err != nil {
		log.Fatal(err)
	}
	return data
}

// 反序列化成Slice
func unMarshalSlice() {
	data := testSlice()
	slice := []map[string]interface{}{}
	err := json.Unmarshal(data, &slice)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("反序列化后slice=%v\n", slice)

}

func main() {
	person := Person{}
	// josn字符串在项目开发中,是通过网络传输或读取文件获得到的
	str := "{\"name\":\"Tom\",\"personAge\":18,\"Birthday\":\"2003-09-08\"}"
	person.unMarshalStruct([]byte(str))
	fmt.Printf("反序列化后 person=%v\n", person)         //反序列化后 person={Tom 18 2003-09-08 0}
	fmt.Printf("反序列化后 person.Age=%T\n", person.Age) //反序列化后 person.Age=int

	unMarshalMap()
	unMarshalSlice()
}

Output:
反序列化后 person={Tom 18 2003-09-08 0}
反序列化后 person.Age=int
反序列化后map=map[Name:红孩儿 address:[火云洞 火焰山] age:1500]
反序列化后slice=[map[Age:5200 Name:[孙悟空 斗战胜佛]] map[Name:猪八戒 address:[高老庄 西天]]]

案例总结/细节说明:
1.测试时可以先创建一个字符串str包含json字符串信息,但需注意在赋值时,要注意转义符的使用(\"\"),再将str转换为[]byte类型进行使用。
2.测试时,也可以直接采用[]byte类型创建josn字符串信息,使用形式:

jsonBlob := []byte(`{"Name":"红孩儿","address":["火云洞","火焰山"],"age":1500}`)

3.在反序列化map、slice类型时,定义变量后不需要进行make操作,因为在unMarshal()函数中封装了make操作;但需注意的是,在输入的参数列表中,对于应用类型必须添加&地址标识符,否则会出现因还没make而导致无分配指针的错误发生。
4.反序列化一个json字符串时,要确保反序列化后的数据类型要和原来序列化前的数据类型一致

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值