json标准库
# json标准库
json包可以实现json的编码和解码,就是将json字符串转换为struct,或者将struct转换为json。
# 1. 核心函数
# 1.1 Marshal
func Marshal(v any) ([]byte, error)
1
将struct编码成json,可以接收任意类型
- 布尔型转换为 JSON 后仍是布尔型,如true -> true
- 浮点型和整数型转换后为JSON里面的常规数字,如 1.23 -> 1.23
- 字符串将以UTF-8编码转化输出为Unicode字符集的字符串,特殊字符比如<将会被转义为\u003c
- 数组和切片被转换为JSON 里面的数组,[]byte类会被转换为base64编码后的字符串,slice的零值被转换为null
- 结构体会转化为JSON对象,并且只有结构体里边以大写字母开头的可被导出的字段才会被转化输出,而这些可导出的字段会作为JSON对象的字符串索引
- 转化一个map 类型的数据结构时,该数据的类型必须是 map[string]T(T 可以是encoding/json 包支持的任意数据类型)
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
Email string
}
func main() {
p := Person{
Name: "zhangsan",
Age: 20,
Email: "zhangsan@mail.com",
}
b, _ := json.Marshal(p)
fmt.Printf("b: %v\n", string(b))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1.2 Unmarshal
func Unmarshal(data []byte, v any) error
1
将json转码为struct结构体
这个函数会把传入的 data 作为一个JSON来进行解析,解析后的数据存储在参数 v 中。这个参数 v 也是任意类型的参数(但一定是一个类型的指针),原因是我们在是以此函数进行JSON 解析的时候,这个函数不知道这个传入参数的具体类型,所以它需要接收所有的类型。
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
Email string
}
func main() {
b := []byte(`{"Name":"zhangsan","Age":20,"Email":"zhangsan@mail.com"}`)
var m Person
json.Unmarshal(b, &m)
fmt.Printf("m: %v\n", m)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2. 核心结构
# 2.1 Decoder
type Decoder struct {
// contains filtered or unexported fields
}
1
2
3
4
2
3
4
从输入流读取并解析json,应用于io流Reader Writer可以扩展到http websocket等场景
package main
import (
"encoding/json"
"fmt"
"os"
)
func main() {
f, _ := os.Open("test.json")
defer f.Close()
d := json.NewDecoder(f)
var v map[string]interface{}
d.Decode(&v)
fmt.Printf("v: %v\n", v)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2.2 Encoder
type Encoder struct {
// contains filtered or unexported fields
}
1
2
3
4
2
3
4
写json到输出流,应用于io流Reader Writer可以扩展到http websocket等场景
package main
import (
"encoding/json"
"os"
)
type Person struct {
Name string
Age int
Email string
Parent []string
}
func main() {
p := Person{
Name: "zhangsan",
Age: 20,
Email: "zhangsan@mail.com",
Parent: []string{"Daddy", "Mom"},
}
f, _ := os.OpenFile("test.json", os.O_WRONLY, 077)
defer f.Close()
d := json.NewEncoder(f)
d.Encode(p)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 奇怪的需求
# 我使用golang语言进行json解析,第一层的key是变化的,再第二层的结果才能转化成结构体
/*
在Go语言中,如果你遇到第一层的key是变化的,需要第二层才能确定结构体的情况,你可以使用map[string]interface{}来处理。
下面是一个示例代码,展示了如何解析具有变化的第一层key的JSON数据,并在第二层将其转换为结构体:
*/
var result map[string]interface{}
err := json.Unmarshal([]byte(msg), &result)
if err != nil {
log.Printf("unmarshal websocket-msg failed err: %s\n", err)
return
}
// 操作第二层的数据用于结构化数据。
cfgs := &startup.FrpConfig{}
commonValue, _ := json.Marshal(result["common"])
err = json.Unmarshal(commonValue, &cfgs.Common)
if err != nil {
log.Printf("unmarshal websocket-msg key is common failed err: %s\n", err)
return
}
// key是变化的。
socksKey := s.Uuid + "_s5"
socksValue, _ := json.Marshal(result[socksKey])
err = json.Unmarshal(socksValue, &cfgs.Socks5)
if err != nil {
log.Printf("unmarshal websocket-msg key is %s failed err: %s\n", socksKey, err)
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# golang反序列化json,在json中不存在的字段设置默认值,如果json有就以json为主
这个需要在框架层是做不了的,只在业务通过if判断来操作。
# 参考资料
编辑 (opens new window)
上次更新: 2023/09/07, 15:38:47