golang Json 序列化 反序列化

本文介绍了Go语言中如何进行结构体到JSON的序列化和反序列化,包括如何自定义序列化的键名和值类型,以及如何将JSON字符串反序列化为结构体和map。同时展示了从JSON反序列化时处理数组和特定字段的方法,以及在实际后端开发中处理前端传来的JSON数据的示例。
摘要由CSDN通过智能技术生成

序列化

结构体转json

package main

import (
	"encoding/json"
	"fmt"
)

// 注意: 结构体转json, 内部成员变量名一定要大写
type IT struct {		// 二次编码
	Company string		`json:"-"` 		  // 定义json不序列化该字段
	Subject []string	`json:"subj"`     // 定义json序列化后的键名为 subj
	IsOk	bool		`json:",string"`  // 定义json序列化后的值为string类型, 即"true"
	Price	float64
}

func main() {
	// 初始化结构体
	stu := IT{
		"人大",
		[]string{"Go","Python","C++"},
		true,
		66.66,
	}
	// 根据内容生成json格式的 []byte
	buf, err := json.Marshal(stu)
	//buf, err := json.MarshalIndent(stu, "", " ")  // 格式化编码
	if err != nil{
		fmt.Println(err)
		return
	}
	// buf 是字节切片,需要转换成string
	fmt.Println(string((buf)))
}

>>>: {"subj":["Go","Python","C++"],"IsOk":"true","Price":66.66}

map转json

func main() {
	m := make(map[string]interface{}, 4)
	m["Company"] = "人大"
	m["Subject"] = []string{"Go","Python","C++"}
	m["IsOk"] = true
	m["Price"] = 66.66
	r, err := json.Marshal(m)
	if err != nil{
		return
	}
	fmt.Println(string(r))
}
>>> :{"Company":"人大","IsOk":true,"Price":66.66,"Subject":["Go","Python","C++"]}

反序列化

json字符串反序列化为结构体

package main

import (
	"encoding/json"
	"fmt"
)

// 注意: json转结构体时,结构体内部成员变量名与json字符串的键名不一致是,要用 二次编码 来转化
type IT struct {		// 二次编码
	Company string		`json:"company"`
	Subject []string	`json:"subject"`
	IsOk	bool		`json:"isOk"`
	Price	float64		`json:"price"`
}

func main() {
	// 注意: json字符串内的 键 是小写,而结构体字段名大写
	// 所以反序列化到结构体时,要利用结构体的二次编码
	jsonBuf := `
		{
			"company":"人大", 
			"subject":[
				"Go",
				"Python",
				"C++"
			],
			"isOk":true,
			"price":66.66
		}
	`
	// 定义结构体变量
	var it IT
	// 反序列: 注意 反序列化时,Unmarshal 是将 []byte 反序列化到目标类型中
	err := json.Unmarshal([]byte(jsonBuf), &it)  // 注意 这里的结构体要用指针, 原因 值类型,引用类型的问题
	if err != nil{
		fmt.Println(err)
		return
	}
	fmt.Printf("it: %+v \n", it)


    // 反序列只想要的字段
	type IT2 struct {		// 二次编码
		Subject []string	`json:"subject"`
	}

	var it2 IT2
	er := json.Unmarshal([]byte(jsonBuf), &it2)
	if er != nil{
		fmt.Println(err)
		return
	}
	fmt.Printf("it2: %+v \n", it2)
}
>>> it: {Company:人大 Subject:[Go Python C++] IsOk:true Price:66.66}
>>> it2: {Subject:[Go Python C++]}

json字符串反序列化为map

func main() {
	// 注意: json字符串内的 键 是小写,而结构体字段名大写
	// 所以反序列化到结构体时,要利用结构体的二次编码
	jsonBuf := `
		{
			"company":"人大", 
			"subject":[
				"Go",
				"Python",
				"C++"
			],
			"isOk":true,
			"price":66.66
		}
	`
	// 反序列化到map
	m := make(map[string]interface{}, 4)
	e := json.Unmarshal([]byte(jsonBuf), &m)  // 注意 这里的map要用指针
	if e != nil{
		fmt.Println(e)
		return
	}
	fmt.Printf("m: %+v \n", m)
	// m: map[company:人大 isOk:true price:66.66 subject:[Go Python C++]]
	// 注意: map在接收反序列化的字符串时,map的键值用的是interface{}, 所以下面的方式使用反序列化后map中值,报错
	//var str string
	//str = m["company"]  // 报错
	//fmt.Println(string(m["company"]))  // 不能转换
	// 正确方式 使用类型断言
	for _, v := range m{
		switch v.(type) {
		case string:
			fmt.Println(v)  // 人大
		case float64:
			fmt.Println(v)  // 66.66
		case bool:
			fmt.Println(v)  // true
		case []interface{}:  // 注意 反序列化map中的键值为 切片 时,类型为  []interface{} 类型
			fmt.Println(v)  // Go Python C++]
		}
	}

    利用类型断言取value的值:
    var devID string
	var paused bool
	for _, i := range m{
		switch v := i.(type) {
		case string:
			devID = v
		case bool:
			paused = v
		}
	}
    也可以这样取值:
	switch  id := m["company"].(type) {
	case string:
		devID = id
	}
	switch  p := m["isOk"].(type) {
	case bool:
		paused = p
	}

    // 使用接口类型转换,将接口类型转成 string
	var svalue interface{}
	svalue = "HaiCoder"
	if value, ok := svalue.(string); ok{
		fmt.Println("Ok Value =", value, "Ok =", ok)
	}else{
		fmt.Println("Failed Value =", value, "Ok =", ok)
	}
}

案例:

前端传输json数据

{
    "type":"send",
    "path":"/home/ccc/桌面/testFilder/ddd",
    "devices":[
        "JV2EWHB-P5BWSQD",
        "SZKZJ24-VFNXWQ4"
    ]
}

后端反序列化


func (s *apiService) postAddFolder(w http.ResponseWriter, r *http.Request) {
	responseMap := make(map[string]interface{})

	defer r.Body.Close()
	bs, _ := ioutil.ReadAll(r.Body) //获取post的数据
	var data map[string]interface{}
	err := json.Unmarshal(bs, &data)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	var folderPath string
	switch Path := data["path"].(type) {
	case string:
		folderPath = Path
	}
	var folderType string
	switch ftype := data["type"].(type) {
	case string:
		folderType = ftype
	}
    
    // 处理数组
	var devicesID []interface {}
	switch dev := data["devices"].(type) {
	case []interface {}:
		devicesID = dev
	}

    for _, devID := range devicesID{
		if value, ok := devID.(string); ok{
			fmt.Printl(value)
		}
	}
    fmt.Printl(folderPath)
    fmt.Printl(folderType)

	responseMap["code"] = 2000
	responseMap["msg"] = "文件夹添加成功!"
	sendJSON(w, responseMap)
}

func sendJSON(w http.ResponseWriter, jsonObject interface{}) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	bs, err := json.MarshalIndent(jsonObject, "", "  ")
	if err != nil {
		// This Marshal() can't fail though.
		bs, _ = json.Marshal(map[string]string{"error": err.Error()})
		http.Error(w, string(bs), http.StatusInternalServerError)
		return
	}
	fmt.Fprintf(w, "%s\n", bs)
}

其他类型json序列化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值