1. 使用标准库
1.1. json序列化相关方法
1. Marshal()Syntax: func Marshal(v interface{}) ([]byte, error)Man: 将Go中数据类型转换为 json 字符串的字节切片2. Unmarshal()Syntax: func Unmarshal(data []byte, v interface{}) errorMan: 反序列化json字符串3. Indent()Syntax: func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) errorMan: 缩进显示json字符串4. Compact()Syntax: func Compact(dst *bytes.Buffer, src []byte) errorMan: 压缩无效空白符
1.2. json序列化
序列化中需要注意的点:
- 因为是调用
json.Mashal(),如果结构体字段使用小写将因为不可导出,而无法完成序列化。 json.Mashal()可以接收指针,因此实际操作中,都是传递指针而不是值如果要对结构体中字段名和json中不一致,需要在结构体定义时指定json中显示的名称
1.2.1. 序列化基本案例
Id和Name有明确指定 json 序列化后的字段名,因此按小写显示
- Hobby中的describe字段小写开头,因此不可导出,在json序列化后的结果中不可见 ```go package main
import ( “encoding/json” “fmt” )
type Student struct {
Id int json:"id"
Name string json:"name"
Hobby []Hobby
}
type Hobby struct { Name string describe string }
func main() { var s0 = Student{ Id: 10001, Name: “张三”, Hobby: []Hobby{ { Name: “游泳”, describe: “游泳。。。。”, }, { Name: “钓鱼”, describe: “台钓”, }, }, } ret, err := json.Marshal(&s0) if err != nil { fmt.Println(“序列化失败”) return } fmt.Println(string(ret)) }
```[root@heyingsheng models]# go run json/marshal.go{"id":10001,"name":"张三","Hobby":[{"Name":"游泳"},{"Name":"钓鱼"}]}
1.2.2. 格式化json
package mainimport ("bytes""encoding/json""fmt""strings")func main() {var str = `{"id":10001,"name":"张三","Hobby":[{"Name":"游泳"},{"Name":"钓鱼"}]}`// 格式化显示json字符串var s = bytes.Buffer{}err := json.Indent(&s, []byte(str), " ", "\t")if err != nil {fmt.Println("格式化失败,err=",err)return}ret := s.String()fmt.Println(ret)fmt.Println(strings.Repeat("##", 20))// 压缩无用的空白符号res := bytes.Buffer{}err = json.Compact(&res, []byte(ret))if err != nil {fmt.Println("格式化失败,err=",err)return}fmt.Println(res.String())}
[root@heyingsheng models]# go run json/json.go{"id": 10001,"name": "张三","Hobby": [{"Name": "游泳"},{"Name": "钓鱼"}]}########################################{"id":10001,"name":"张三","Hobby":[{"Name":"游泳"},{"Name":"钓鱼"}]}
1.3. json反序列化
1.3.1. 简单反序列化
package mainimport ("encoding/json""fmt")type User struct {Name string `json:"name"`Class []string `json:"class"`}func main() {str := `{"10001": {"name": "张三", "class": ["物理","化学","生物"]}}`var user01 map[string]Userif err := json.Unmarshal([]byte(str), &user01); err != nil {fmt.Println("反序列化失败,err=", err)return}fmt.Printf("type:%T, value:%v\n", user01, user01)fmt.Println(user01["10001"].Class[0])}
[root@heyingsheng models]# go run json/unmarshal.gotype:map[string]main.User, value:map[10001:{张三 [物理 化学 生物]}]物理
1.3.2. 使用空接口接收数据
空接口可以接收任何结构的json字符串,但是非常难以转换为可操作的go语言数据类型,因为涉及到类型的断言!
package mainimport ("encoding/json""fmt")type User struct {Name string `json:"name"`Class []string `json:"class"`}func main() {str := `{"10001": {"name": "张三", "class": ["物理","化学","生物"]}}`var user01 interface{}if err := json.Unmarshal([]byte(str), &user01); err != nil {fmt.Println("反序列化失败,err=", err)return}fmt.Printf("type:%T, value:%v\n", user01, user01)// 使用类型断言才能取值if user, ok := user01.(map[string]interface {}); ok {fmt.Printf("type:%T, value:%v\n", user["10001"], user["10001"])}}
[root@heyingsheng models]# go run json/unmarshal.gotype:map[string]interface {}, value:map[10001:map[class:[物理 化学 生物] name:张三]]type:map[string]interface {}, value:map[class:[物理 化学 生物] name:张三]
1.4. json的tag
1.4.1. 忽略字段
type User struct {Name string `json:"name"`UID string `json:"uid"`Address string `json:"-"` // 忽略该字段Password string `json:"password,omitempty"` // 忽略零值字段Phone `json:"phone"` // 指定json后,将单层结构转为多层结构*Score `json:"score,omitempty"` // 如果字段为空则忽略,必须使用结构体指针,否则不行}type Phone struct {TelPhone string `json:"tel_phone,omitempty"`Mobile string `json:"mobile,omitempty"`}type Score struct {MathScore int `json:"math_score"`MusicScore int `json:"music_score"`}func main() {user01 := User{Name: "ZhangSan",UID: "0001",Address: "南京",Password: "",}ret, _ := json.Marshal(user01)fmt.Println(string(ret))}
[root@duduniao json]# go run main.go{"name":"ZhangSan","uid":"0001","phone":{}}
1.4.2. 类型转换
在开发中,经常会出现服务调用接口,要求传递json中value为字符串,而代码结构体中为 bool 或者 int等其它类型。这种需求可以通过自定义的方法来实现转换,但是也有根据简单的方法,就是使用 tag 处理。
type Student struct {Name string `json:"name"`Age int8 `json:"age,string"`IsAdmin bool `json:"is_admin,string"`}func main() {s1 := Student{"张三",int8(18),false,}ret, _ := json.Marshal(s1)fmt.Println(string(ret))fmt.Println(strings.Repeat("--", 20))str := `{"name":"李四","age":"39","is_admin":"true"}`_ = json.Unmarshal([]byte(str), &s1)fmt.Printf("%#v\n", s1)}
[root@duduniao json]# go run main.go{"name":"张三","age":"18","is_admin":"false"}----------------------------------------main.Student{Name:"李四", Age:39, IsAdmin:true}
2. 使用simpleJson处理json
在对象序列化为 json 字符串时,或者将json对象反序列化并赋值给一个结构体指针,这两种场景很适合使用标准库中得 json 包,但是如果只是从现有得 json 中某一些字段得值,那么可以考虑使用 simplejson 的链式调用完成处理。
2.1. simplejson常用方法
# "github.com/bitly/go-simplejson"1. Json 结构体type Json struct {// contains filtered or unexported fields}2. 构造函数func NewJson(body []byte) (*Json, error)3. 从 io.Reader 接口构造 Json对象func NewFromReader(r io.Reader) (*Json, error)4. 断言相关的方法func (j *Json) String() (string, error)func (j *Json) Int() (int, error)func (j *Json) Int64() (int64, error)func (j *Json) Uint64() (uint64, error)func (j *Json) Bool() (bool, error)func (j *Json) Bytes() ([]byte, error)func (j *Json) StringArray() ([]string, error)func (j *Json) Interface() interface{}func (j *Json) Map() (map[string]interface{}, error)func (j *Json) Array() ([]interface{}, error)5. 保证返回指定类型的结果, args 设定默认值func (j *Json) MustInt(args ...int) intfunc (j *Json) MustString(args ...string) stringfunc (j *Json) MustFloat64(args ...float64) float64func (j *Json) MustBool(args ...bool) boolfunc (j *Json) MustStringArray(args ...[]string) []stringfunc (j *Json) MustMap(args ...map[string]interface{}) map[string]interface{}func (j *Json) MustArray(args ...[]interface{}) []interface{}6. 在map类型中,根据key取值func (j *Json) Get(key string) *Json7. 更新jsonfunc (j *Json) Del(key string)func (j *Json) Set(key string, val interface{})8. 序列化func (j *Json) Encode() ([]byte, error)func (j *Json) EncodePretty() ([]byte, error) // 带缩进
2.2. 案例
测试的 Json 字符串如下
{"deploy_type":"task","uniqid":"task-01","labels":{"deploy_type":"db"},"callback_url":"https://xxx.xxx.xxx","tasks":[{"cluster_type":"vm_cluster","deploy_type":"vm_cluster","action":"create","labels":{"deploy_type":"cluster"},"uniqid":"cluster01","name":"cluster01","options":{"cadvisor":true}}]}
2.2.1. 取值
func main() {sJson, err := simplejson.NewJson([]byte(str))if err != nil {fmt.Printf("New json failed, err:%s\n", err.Error())return}// 取labelsres1 := sJson.Get("labels").Get("deploy_type").MustString("null")tmp1, _ := json.Marshal(sJson.Get("tasks").MustArray()[0]) // 返回值为 interface,需要重新序列化tmp2, _ := simplejson.NewJson(tmp1)res2 := tmp2.Get("labels").Get("deploy_type").MustString()fmt.Printf("res1:%s,res2:%s\n", res1, res2)}
2.2.2 修改值
func main() {sJson, err := simplejson.NewJson([]byte(str))if err != nil {fmt.Printf("New json failed, err:%s\n", err.Error())return}// 删除值sJson.Del("tasks") // 删除task字段res1, _:= sJson.EncodePretty()fmt.Println(string(res1))// 修改值sJson.Set("labels", false) // 修改labels字段res2, _:= sJson.EncodePretty()fmt.Println(string(res2))}
