文章目录
- 目的
- Decoding(解析数据)
- Encoding(创建数据)
- 总结
目的
JSON 是一种非常流行的数据交换格式,是JavaScript中原生支持的一种数据,因为其简单方便,所以也经常用在不同程序、不同语言间数据交互。这篇文章将介绍在Golang中使用JSON相关内容( encoding/json )。
Decoding(解析数据)
可以使用 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(创建数据)
可以使用 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
等方法。