Go语言基础(二)读写json字符串

本文主要介绍了Go语言中读写json的相关操作。

关键词:golang

将json字符串反序列化成对象

以飞书机器人富文本的消息体为例

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
{
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": "项目更新通知",
"content": [
[
{
"tag": "text",
"text": "项目有更新: "
},
{
"tag": "a",
"text": "请查看",
"href": "http://www.example.com/"
},
{
"tag": "at",
"user_id": "ou_18eac8********17ad4f02e8bbbb"
}
]
]
}
}
}
}

核心代码

1
func Unmarshal(data []byte, v any) error

map映射方法

直接用map[string]interface{}一步到位

这种方法比较粗暴,可以快速映射到go里面的对象

缺点就是在读json里的字段时需要先用.推断出来空接口的类型,导致代码不太好看hhh...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func main() {
msg := map[string]interface{}{}
jsonDATA, err := ioutil.ReadFile("data.json")
if err != nil {
panic(err)
}
// fmt.Printf("jsonDATA: %s\n", string(jsonDATA))
err = json.Unmarshal(jsonDATA, &msg)
if err != nil {
panic(err)
}
fmt.Printf("msg: %v\n", msg)
content := msg["content"].(map[string]interface{})
fmt.Printf("msg[\"content\"][\"post\"][\"zh_cn\"]: %v\n", content["post"].(map[string]interface{})["zh_cn"])
fmt.Printf("msg[\"content\"][\"post\"][\"zh_cn\"][\"title\"]: %v\n", content["post"].(map[string]interface{})["zh_cn"].(map[string]interface{})["title"])
fmt.Printf("msg[\"content\"][\"post\"][\"zh_cn\"][\"content\"]: %v\n", content["post"].(map[string]interface{})["zh_cn"].(map[string]interface{})["content"])
_content := content["post"].(map[string]interface{})["zh_cn"].(map[string]interface{})["content"].([]interface{})[0].([]interface{}) // 二维json数组
fmt.Printf("content[0]: %v\n", _content[0])
fmt.Printf("content[1]: %v\n", _content[1])
fmt.Printf("content[2]: %v\n", _content[2])
}

结构体映射方法

这种方法虽然比较复杂,但是好理解

balabala写了一堆,最后自己没搞出来。

如果单独用一种方法比较复杂的话,那最优解就是两种方式结合在一起。

1
2
3
4
5
6
7
8
  JSON类型             Go类型                
---------------------------------------------
JSON objects <--> map[string]interface{}
JSON arrays <--> []interface{}
JSON booleans <--> bool
JSON numbers <--> float64
JSON strings <--> string
JSON null <--> nil

不过既然已经有好轮子了干嘛还要自己造呢~自己专注代码逻辑就OK了,其他的就不要考虑了

使用工具映射

Paste JSON as Code

在线版:https://app.quicktype.io/

VScode 插件

生成代码步骤:

  1. 打开json文件

  2. 打开VScode command,Mac上的快捷键是 Command + Shift + P,选择Open quicktype for JSON,如果语言不对的话可以使用Set quicktype target language指定生成代码的语言

  3. 展示生成的结果

    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    // Generated by https://quicktype.io
    //
    // To change quicktype's target language, run command:
    //
    // "Set quicktype target language"

    type Data struct {
    MsgType string `json:"msg_type"`
    Content DataContent `json:"content"`
    }

    type DataContent struct {
    Post Post `json:"post"`
    }

    type Post struct {
    ZhCN ZhCN `json:"zh_cn"`
    }

    type ZhCN struct {
    Title string `json:"title"`
    Content [][]ContentElement `json:"content"`
    }

    type ContentElement struct {
    Tag string `json:"tag"`
    Text *string `json:"text,omitempty"`
    Href *string `json:"href,omitempty"`
    UserID *string `json:"user_id,omitempty"`
    }

    func main() {
    msg := &Data{}
    fmt.Printf("msg: %v\n", msg)
    jsonDATA, err := ioutil.ReadFile("data.json")
    if err != nil {
    panic(err)
    }
    // fmt.Printf("jsonDATA: %s\n", string(jsonDATA))
    err = json.Unmarshal(jsonDATA, msg)
    if err != nil {
    panic(err)
    }
    fmt.Printf("msg.Content: %v\n", msg.Content)
    fmt.Printf("msg.MsgType: %v\n", msg.MsgType)
    }


    JSON tag中的omitempty 关键字,表示这条信息如果没有提供,在序列化成 json 的时候就不要包含其默认值

把对象序列化成字符串

核心代码

1
2
jsonDATA, err = json.Marshal(msg) // 不带缩进 
json.MarshalIndent(c, "", " ") // 带缩进

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func main() {
msg := &Data{}
fmt.Printf("msg: %v\n", msg)
jsonDATA, err := ioutil.ReadFile("data.json")
if err != nil {
panic(err)
}
// fmt.Printf("jsonDATA: %s\n", string(jsonDATA))
err = json.Unmarshal(jsonDATA, msg)
if err != nil {
panic(err)
}
fmt.Printf("msg.Content: %v\n", msg.Content)
fmt.Printf("msg.MsgType: %v\n", msg.MsgType)
// jsonDATA, err = json.Marshal(msg) // 不带缩进
jsonDATA, err = json.MarshalIndent(msg, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("string(jsonDATA): %v\n", string(jsonDATA))
}