参考文章:
go 官方package: /json
特别好的文章:理解 Go 中的 JSON
JSON是一种轻量级的数据交换格式,常用在前后端数据交换,go的 encoding/json 提供了对json的支持
一、序列化
GO提供了 Marshal 方法:Go Struct转换为JSON对象,函数签名:
func Marshal(v interface{}) ([]byte, error)
举例:
type Person struct {
Name string
Gender string
Age uint32
}
// 默认初始化
p := Person{"a", "male", 23}
fmt.Println(p)
fmt.Printf("%v\n", p) //{a male 23}
// 指定成员初始化
p1 := Person{Name: "wsq", Gender: "male"}
fmt.Println(p1) //{wsq male 0}
// 序列化
b, _ := json.Marshal(p)
fmt.Println(string(b)) //{"Name":"a","Gender":"male","Age":23}
}
- 只支持struct中导出的field才能被序列化,即
首字母大写的field
- GO中不是所有类型都支持序列化,其中key只支持
string
- 无法对
channel,complex,function
序列化 - 数据中如存在循环引用,不支持序列化,因为会递归。
-
pointer
序列化后是其指向的值或者是nil
Struct Tag
指定 JSON filed name
序列化后的json串中的name
一般为小写,我们通过struct tag
实现
指定field为empty
使用omitempty
告诉Marshal函数,如field对应类型为zero-value,那么序列化的json对象中不包含此field
跳过field
仅使用"-"
表示跳过指定的field,保护某些字段不被序列化
type Person struct {
Name string `json:"name"`
Gender string `json:"gender"`
Age uint32 `json:"age,omitempty"`
Passwd string `json:"-"`
}
// 默认初始化
p := Person{"a", "male", 23, "mimi"}
fmt.Println(p)
fmt.Printf("%v\n", p) //{a male 23}
// 指定成员初始化
p1 := Person{Name: "wsq", Gender: "male"}
fmt.Println(p1) //{wsq male 0}
// 序列化
b, _ := json.Marshal(p)
fmt.Println(string(b)) //{"Name":"a","Gender":"male","Age":23}
// 反序列化
var pp Person
err := json.Unmarshal(b, &pp)
if err != nil {
errors.New("unmarshal error")
}
fmt.Printf("%T, %v\n", pp, pp)
// Struct Tag
// 指定JSON的field name
c, _ := json.Marshal(p)
fmt.Println(string(c)) //{"name":"a","gender":"male","age":23}
// 指定field是empty时的行为
d, _ := json.Marshal(p1)
fmt.Println(string(d)) //{"name":"wsq","gender":"male"}
// 跳过指定field
importPerson := Person{Name: "wsq", Passwd: "password"}
importPersonMar, _ := json.Marshal(importPerson)
fmt.Println(string(importPersonMar)) //{"name":"wsq","gender":""}
二、反序列化
发序列化函数 Unmarshal ,函数签名:
func Unmarshal(data []byte, v interface{}) error
此时,我们需要创建一个可序列化的byte切片,将其转换为struct。
默认的json支持:bool, float64, string,nil
几种Go类型
反序列化处理未知JSON数据格式
使用interface{}
存储
举例:
b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
var f interface{}
err := json.Unmarshal(b, &f)
if err != nil {
errors.New("unmarshal error")
}
fmt.Printf("%T, %v\n", f, f)
输出:
类型: map[string]interface {}
内容: map[Age:6 Name:Wednesday Parents:[Gomez Morticia]]
可以发现,此时key
是string
类型,value是存储在interface {}
中的,我们可以通过type assertion
获取:
m := f.(map[string]interface{})
for k, v := range m {
switch vv := v.(type) {
case string:
fmt.Println(k, "is string", vv)
case float64:
fmt.Println(k, "is float64", vv)
case []interface{}:
fmt.Println(k, "is an array:")
for i, u := range vv {
fmt.Println(i, u)
}
default:
fmt.Println(k, "is of a type I don't know how to handle")
}
}
反序列化处理slice、map、pointer
举例:
type FamilyMember struct {
Name string
Age int
Parents []string
}
func main() {
b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
var n FamilyMember
json.Unmarshal(b, &n)
fmt.Printf("%T, %v\n", n, n)
}
struct中存在一个slice
类型,默认值为nil。
- 序列化时,若不为
nil
,则解引用获得其指向的值,然后序列化 - 反序列化时首先对其初始化为
nil
,之后再赋值
三、其他序列化函数
函数:
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w: w, escapeHTML: true}
}
// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
func (enc *Encoder) Encode(v interface{}) error {
// ...
}
举例:
除了 marshal 和 unmarshal 函数,Go 还提供了 Decoder 和 Encoder 对 stream JSON 进行处理。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
var err error
person1 := Person{"张三", 30}
// 编码结果暂存到 buffer
bytes1 := new(bytes.Buffer)
_ = json.NewEncoder(bytes1).Encode(person1)
if err == nil {
fmt.Print(" 编码结果: ", string(bytes1.Bytes()))
}
// 解码
str2 := bytes1.String()
var person2 Person
// 创建一个 string reader 作为参数
err = json.NewDecoder(strings.NewReader(str2)).Decode(&person2)
if err == nil {
fmt.Println(" 解码结果: ", person2.Name, person2.Age)
}
}
四、nest struct序列化
type App struct {
Id string `json:"id"`
}
type Org struct {
Name string `json:"name"`
}
type AppWithOrg struct {
App
Org
}
func main() {
data := []byte(`
{
"id": "k34rAT4",
"name": "My Awesome Org"
}
`)
var b AppWithOrg
json.Unmarshal(data, &b)
fmt.Printf("%#v", b)
a := AppWithOrg{
App: App{
Id: "k34rAT4",
},
Org: Org{
Name: "My Awesome Org",
},
}
data, _ = json.Marshal(a)
fmt.Println(string(data))
}
vscode 工具相关
1. 删除当前行ctrl + shift +k
2. vscode插件 String Manipulation 字符串转换处理(驼峰、大写开头、下划线等等)
使用时ctrl+shift+p 输入camel即可
3. ctrl+f5直接编译简单go文件
参考:/?id=10
/post/5d5cbc20f265da03ab425227