【Golang】使用 - JSON序列化与反序列化

Posted by 西维蜀黍 on 2020-03-30, Last Modified on 2023-07-26

struct转JSON

我们可以在struct的attribute后指定该struct被序列化成JSON后的key的值,这被称为Struct Tag

Struct tag 可以决定 Marshal 和 Unmarshal 函数如何在序列化和反序列化数据时,JSON key的值。

如果没有指定,则取该attribute对应全小写字符串作为key的值。

package main

import (
	"encoding/json"
	"fmt"
)

type User struct {
	UserName string `json:"username"`
	NickName string `json:"nickname"`
	Age      int
	Birthday string `json:"birth"`
	Sex      string
	Email    string
	Phone    string
}

/*结构体转json*/
func testStruct() {
	user1 := &User{
		UserName: "user1",
		NickName: "上课看似",
		Age:      18,
		Birthday: "2008/8/8",
		Sex:      "男",
		Email:    "mahuateng@qq.com",
		Phone:    "110",
	}

	dataBytes, err := json.Marshal(user1)
	if err != nil {
		fmt.Printf("json.marshal failed, err:", err)
		return
	}

	fmt.Printf("%s \n", string(dataBytes))
}

func main() {
	testStruct()
	fmt.Println("----")
}

//output
{"username":"user1","nickname":"上课看似","Age":18,"birth":"2008/8/8","Sex":"男","Email":"mahuateng@qq.com","Phone":"110"} 
----

omitempty - 指定 field 是 empty 时的行为

使用 omitempty 会告诉 Marshal 函数:当 field 的值是对应类型的 zero-value时,序列化之后的 JSON object 中不包含此 field:

type MyStruct struct {
    SomeField string `json:"some_field,omitempty"`
}

m := MyStruct{}
b, err := json.Marshal(m) //{}

如果 SomeField == “” ,序列化之后的对象就是 {}

跳过 field

Struct tag “-” 表示在序列化struct时跳过指定的 filed:

type MyStruct struct {
    SomeField string `json:"some_field"`
    Passwd string `json:"-"`
}
m := MyStruct{}
b, err := json.Marshal(m) //{"some_feild":""}

即序列化的时候不输出,这样可以有效保护需要保护的字段不被序列化。

临时粘合两个struct

通过嵌入struct的方式:

package main

import (
	"encoding/json"
)

type BlogPost struct {
	URL   string `json:"url"`
	Title string `json:"title"`
}

type Analytics struct {
	Visitors  int `json:"visitors"`
	PageViews int `json:"page_views"`
}

func main() {
	post := &BlogPost{
		URL:   "test.com",
		Title: "t",
	}

	analytics := &Analytics{
		Visitors:  1,
		PageViews: 2,
	}

	bytes, err := json.Marshal(struct {
		*BlogPost
		*Analytics
	}{post, analytics})

	println(string(bytes))
	println(err)
}

用字符串传递数字

type TestObject struct {
    Field1 int    `json:",string"`
}

这个对应的json是 {"Field1": "100"}

如果json是 {"Field1": 100} 则会报错

Map转JSON(JSON序列化)

package main

import (
	"encoding/json"
	"fmt"
)

func testMap() {
	mmp := make(map[string]interface{})

	mmp["username"] = "user"
	mmp["age"] = 19
	mmp["sex"] = "man"

	data, err := json.Marshal(mmp)
	if err != nil {
		fmt.Println("json marshal failed,err:", err)
		return
	}
	fmt.Printf("%s\n", string(data))
}

func main() {
	testMap()
	fmt.Println("----")
}

// output
{"age":19,"sex":"man","username":"user"}
----

slice转JSON(JSON序列化)

package main

import (
	"encoding/json"
	"fmt"
)

func testSlice() {
	var map1 map[string]interface{}
	var slice1 []map[string]interface{}
	map1 = make(map[string]interface{})
	map1["username"] = "user1"
	map1["age"] = 18
	map1["sex"] = "man"

	slice1 = append(slice1, map1)

	map1 = make(map[string]interface{})
	map1["username"] = "user2"
	map1["age"] = 29
	map1["sex"] = "female"
	slice1 = append(slice1, map1)

	bytes, err := json.Marshal(slice1)
	if err != nil {
		fmt.Println("json.marshal failed, err:", err)
		return
	}
	fmt.Printf("%slice1\n", string(bytes))

	slice2 := make([]int, 3)
	slice2[0] = 0
	slice2[1] = 1
	slice2[2] = 2
	bytes, err = json.Marshal(slice2)
	if err != nil {
		fmt.Println("json.marshal failed, err:", err)
		return
	}
	fmt.Printf("%s\n", string(bytes))
}

func main() {
	testSlice()
}

// output
[{"age":18,"sex":"man","username":"user1"},{"age":29,"sex":"female","username":"user2"}]lice1
[0,1,2]

JSON 转 struct(JSON反序列化)

package main

import (
	"encoding/json"
	"fmt"
)

type User struct {
	UserName string `json:"username"`
	NickName string `json:"test_nickname"`
	Age      int
	Birthday string
	Sex      string
	Email    string
	Phone    string
}

func main() {
	str := `{"username":"user1","test_nickname":"上课看似","Age":18,"Birthday":"2008/8/8","Sex":"男","Email":"test@qq.com","Phone":"110"}`

	var user1 User
	err := json.Unmarshal([]byte(str), &user1)
	if err != nil {
		fmt.Println("Unmarshal failed, ", err)
		return
	}
	fmt.Printf("%+v", user1)
}

// output
{UserName:user1 NickName:上课看似 Age:18 Birthday:2008/8/8 Sex: Email:test@qq.com Phone:110}

JSON 转 map(JSON反序列化)

package main

import (
	"encoding/json"
	"fmt"
)

func serializeMap() (ret string, err error) {
	var m map[string]interface{}
	m = make(map[string]interface{})
	m["username"] = "user1"
	m["age"] = 18
	m["sex"] = "man"

	str, err := json.Marshal(m)
	if err != nil {
		err = fmt.Errorf("json.marshal failed, err: %v", err)
		return
	}

	ret = string(str)
	return
}

func main() {
	str, err := serializeMap()
	if err != nil {
		fmt.Println("test map failed, ", err)
		return
	}
	println(str)

	var m map[string]interface{}
	err = json.Unmarshal([]byte(str), &m)
	if err != nil {
		fmt.Println("Unmarshal failed, ", err)
		return
	}
	fmt.Println(m)
}

// output
{"age":18,"sex":"man","username":"user1"}
map[age:18 sex:man username:user1]

Reference