JSON 是一种非常流行的数据交换格式,是JavaScript中原生支持的一种数据,因为其简单方便,所以也经常用在不同程序、不同语言间数据交互。这篇文章将介绍在Golang中使用JSON相关内容( encoding/json )。
可以使用 encoding/json
包的 func Unmarshal(data []byte, v any) error
方法,从原始JSON字符串中解析对应内容到指定数据结构中。比如下面示例将解析数据到结构体中:
package main
import (
"encoding/json"
"fmt"
)
type data struct {
Num int `json:"num"`
Bl bool `json:"bl"`
Str string `json:"str"`
Arr []int `json:"arr"`
Obj struct {
Num int `json:"num"`
} `json:"obj"`
} // 用于接收JSON字符串中内容的结构体类型
func main() {
var j data
s := `{
"num": 233,
"bl": true,
"str": "naisu",
"arr": [
22,
33
],
"obj": {
"num": 777
}
}` // 原始JSON字符串
json.Unmarshal([]byte(s), &j) // 从原始数据中解析内容填充结构体对象
fmt.Println(j.Num, j.Bl, j.Str, j.Arr, j.Obj)
}
上面例子操作比较简单,但是演示了JSON的几种基本的数据格式。需要注意的是 结构体中字段名称首字母需要大写 。
如果有现成的JSON数据范本的话可以通过下面工具直接生成结构体类型声明:
https://mholt.github.io/json-to-go/
上面演示中结构体类型中字段和原始JSON数据中字段是可以一一匹配上的,但如果两者无法一一匹配,也可以进行解析。 结构体中有而JSON中没有的字段,那么解析之后结构体对象中这些字段将会填充默认值。结构体中没有而JSON中有的字段,那么解析时会忽略这些字段。
上面方式对于已知格式的JSON数据解析时比较好用,但是对于未知格式的JSON数据解析就不太好用了。通常可以使用泛型来处理,比如可以使用 map[string]interface{}
接收对象,使用 []interface{}
接收数组。请看下面示例:
package main
import (
"encoding/json"
"fmt"
)
func main() {
var j map[string]interface{}
s := `{
"num": 233,
"bl": true,
"str": "naisu",
"arr": [
22,
33
],
"obj": {
"num": 777
}
}` // 原始JSON字符串
if err := json.Unmarshal([]byte(s), &j); err != nil {
fmt.Println(err)
}
fmt.Println(j)
for k, v := range j {
switch vv := v.(type) {
case bool:
fmt.Println(k, "is bool", vv)
case string:
fmt.Println(k, "is string", vv)
case float64:
fmt.Println(k, "is float64", vv)
case []interface{}:
fmt.Println(k, "is array:")
for i, u := range vv {
fmt.Println(i, u)
}
case map[string]interface{}:
fmt.Println(k, "is oject:", v)
default:
fmt.Println(k, "is of a type I don't know how to handle")
}
}
}
现在有泛型了, interface{}
也可以使用 any
来代替。
可以使用 encoding/json
包的 func Marshal(v any) ([]byte, error)
方法将Golang数据类型生成JSON字符串。比如下面例子:
package main
import (
"encoding/json"
"fmt"
)
type data struct {
Num int `json:"num"`
Bl bool `json:"bl"`
Str string `json:"str"`
Arr []int `json:"arr"`
Obj struct {
Num int `json:"num"`
} `json:"obj"`
} // 用于接收JSON字符串中内容的结构体类型
func main() {
j := data{
Num: 233,
Bl: true,
Str: "naisu",
}
j.Arr = append(j.Arr, 22, 33)
j.Obj.Num = 777
b, err := json.Marshal(j) // 将结构体转换成JSON字符串
if err != nil {
fmt.Println(err)
}
fmt.Println(string(b))
}
数据也可以通过接口或泛型等类型进行转换:
package main
import (
"encoding/json"
"fmt"
)
func main() {
j := make(map[string]any)
j["Num"] = 233
j["Bl"] = true
j["Str"] = "naisu"
Arr := []int{}
Arr = append(Arr, 22, 33)
j["Arr"] = Arr
Obj := make(map[string]any)
Obj["Num"] = 777
j["Obj"] = Obj
b, err := json.Marshal(j) // 将结构体转换成JSON字符串
if err != nil {
fmt.Println(err)
}
fmt.Println(string(b))
}
对于JSON的操作主要内容就是这些了。如果需要更加细节的解析和创建的控制可以使用 MarshalJSON
或者 UnmarshalJSON
等方法。