1. 使用标准库

1.1. json序列化相关方法

  1. 1. Marshal()
  2. Syntax: func Marshal(v interface{}) ([]byte, error)
  3. Man: Go中数据类型转换为 json 字符串的字节切片
  4. 2. Unmarshal()
  5. Syntax: func Unmarshal(data []byte, v interface{}) error
  6. Man: 反序列化json字符串
  7. 3. Indent()
  8. Syntax: func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error
  9. Man: 缩进显示json字符串
  10. 4. Compact()
  11. Syntax: func Compact(dst *bytes.Buffer, src []byte) error
  12. Man: 压缩无效空白符

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)) }

  1. ```
  2. [root@heyingsheng models]# go run json/marshal.go
  3. {"id":10001,"name":"张三","Hobby":[{"Name":"游泳"},{"Name":"钓鱼"}]}

1.2.2. 格式化json

  1. package main
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "strings"
  7. )
  8. func main() {
  9. var str = `{"id":10001,"name":"张三","Hobby":[{"Name":"游泳"},{"Name":"钓鱼"}]}`
  10. // 格式化显示json字符串
  11. var s = bytes.Buffer{}
  12. err := json.Indent(&s, []byte(str), " ", "\t")
  13. if err != nil {
  14. fmt.Println("格式化失败,err=",err)
  15. return
  16. }
  17. ret := s.String()
  18. fmt.Println(ret)
  19. fmt.Println(strings.Repeat("##", 20))
  20. // 压缩无用的空白符号
  21. res := bytes.Buffer{}
  22. err = json.Compact(&res, []byte(ret))
  23. if err != nil {
  24. fmt.Println("格式化失败,err=",err)
  25. return
  26. }
  27. fmt.Println(res.String())
  28. }
  1. [root@heyingsheng models]# go run json/json.go
  2. {
  3. "id": 10001,
  4. "name": "张三",
  5. "Hobby": [
  6. {
  7. "Name": "游泳"
  8. },
  9. {
  10. "Name": "钓鱼"
  11. }
  12. ]
  13. }
  14. ########################################
  15. {"id":10001,"name":"张三","Hobby":[{"Name":"游泳"},{"Name":"钓鱼"}]}

1.3. json反序列化

1.3.1. 简单反序列化

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. )
  6. type User struct {
  7. Name string `json:"name"`
  8. Class []string `json:"class"`
  9. }
  10. func main() {
  11. str := `{"10001": {"name": "张三", "class": ["物理","化学","生物"]}}`
  12. var user01 map[string]User
  13. if err := json.Unmarshal([]byte(str), &user01); err != nil {
  14. fmt.Println("反序列化失败,err=", err)
  15. return
  16. }
  17. fmt.Printf("type:%T, value:%v\n", user01, user01)
  18. fmt.Println(user01["10001"].Class[0])
  19. }
  1. [root@heyingsheng models]# go run json/unmarshal.go
  2. type:map[string]main.User, value:map[10001:{张三 [物理 化学 生物]}]
  3. 物理

1.3.2. 使用空接口接收数据

空接口可以接收任何结构的json字符串,但是非常难以转换为可操作的go语言数据类型,因为涉及到类型的断言!

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. )
  6. type User struct {
  7. Name string `json:"name"`
  8. Class []string `json:"class"`
  9. }
  10. func main() {
  11. str := `{"10001": {"name": "张三", "class": ["物理","化学","生物"]}}`
  12. var user01 interface{}
  13. if err := json.Unmarshal([]byte(str), &user01); err != nil {
  14. fmt.Println("反序列化失败,err=", err)
  15. return
  16. }
  17. fmt.Printf("type:%T, value:%v\n", user01, user01)
  18. // 使用类型断言才能取值
  19. if user, ok := user01.(map[string]interface {}); ok {
  20. fmt.Printf("type:%T, value:%v\n", user["10001"], user["10001"])
  21. }
  22. }
  1. [root@heyingsheng models]# go run json/unmarshal.go
  2. type:map[string]interface {}, value:map[10001:map[class:[物理 化学 生物] name:张三]]
  3. type:map[string]interface {}, value:map[class:[物理 化学 生物] name:张三]

1.4. json的tag

1.4.1. 忽略字段

  1. type User struct {
  2. Name string `json:"name"`
  3. UID string `json:"uid"`
  4. Address string `json:"-"` // 忽略该字段
  5. Password string `json:"password,omitempty"` // 忽略零值字段
  6. Phone `json:"phone"` // 指定json后,将单层结构转为多层结构
  7. *Score `json:"score,omitempty"` // 如果字段为空则忽略,必须使用结构体指针,否则不行
  8. }
  9. type Phone struct {
  10. TelPhone string `json:"tel_phone,omitempty"`
  11. Mobile string `json:"mobile,omitempty"`
  12. }
  13. type Score struct {
  14. MathScore int `json:"math_score"`
  15. MusicScore int `json:"music_score"`
  16. }
  17. func main() {
  18. user01 := User{
  19. Name: "ZhangSan",
  20. UID: "0001",
  21. Address: "南京",
  22. Password: "",
  23. }
  24. ret, _ := json.Marshal(user01)
  25. fmt.Println(string(ret))
  26. }
  1. [root@duduniao json]# go run main.go
  2. {"name":"ZhangSan","uid":"0001","phone":{}}

1.4.2. 类型转换

在开发中,经常会出现服务调用接口,要求传递json中value为字符串,而代码结构体中为 bool 或者 int等其它类型。这种需求可以通过自定义的方法来实现转换,但是也有根据简单的方法,就是使用 tag 处理。

  1. type Student struct {
  2. Name string `json:"name"`
  3. Age int8 `json:"age,string"`
  4. IsAdmin bool `json:"is_admin,string"`
  5. }
  6. func main() {
  7. s1 := Student{
  8. "张三",
  9. int8(18),
  10. false,
  11. }
  12. ret, _ := json.Marshal(s1)
  13. fmt.Println(string(ret))
  14. fmt.Println(strings.Repeat("--", 20))
  15. str := `{"name":"李四","age":"39","is_admin":"true"}`
  16. _ = json.Unmarshal([]byte(str), &s1)
  17. fmt.Printf("%#v\n", s1)
  18. }
  1. [root@duduniao json]# go run main.go
  2. {"name":"张三","age":"18","is_admin":"false"}
  3. ----------------------------------------
  4. main.Student{Name:"李四", Age:39, IsAdmin:true}

2. 使用simpleJson处理json

在对象序列化为 json 字符串时,或者将json对象反序列化并赋值给一个结构体指针,这两种场景很适合使用标准库中得 json 包,但是如果只是从现有得 json 中某一些字段得值,那么可以考虑使用 simplejson 的链式调用完成处理。

2.1. simplejson常用方法

  1. # "github.com/bitly/go-simplejson"
  2. 1. Json 结构体
  3. type Json struct {
  4. // contains filtered or unexported fields
  5. }
  6. 2. 构造函数
  7. func NewJson(body []byte) (*Json, error)
  8. 3. io.Reader 接口构造 Json对象
  9. func NewFromReader(r io.Reader) (*Json, error)
  10. 4. 断言相关的方法
  11. func (j *Json) String() (string, error)
  12. func (j *Json) Int() (int, error)
  13. func (j *Json) Int64() (int64, error)
  14. func (j *Json) Uint64() (uint64, error)
  15. func (j *Json) Bool() (bool, error)
  16. func (j *Json) Bytes() ([]byte, error)
  17. func (j *Json) StringArray() ([]string, error)
  18. func (j *Json) Interface() interface{}
  19. func (j *Json) Map() (map[string]interface{}, error)
  20. func (j *Json) Array() ([]interface{}, error)
  21. 5. 保证返回指定类型的结果, args 设定默认值
  22. func (j *Json) MustInt(args ...int) int
  23. func (j *Json) MustString(args ...string) string
  24. func (j *Json) MustFloat64(args ...float64) float64
  25. func (j *Json) MustBool(args ...bool) bool
  26. func (j *Json) MustStringArray(args ...[]string) []string
  27. func (j *Json) MustMap(args ...map[string]interface{}) map[string]interface{}
  28. func (j *Json) MustArray(args ...[]interface{}) []interface{}
  29. 6. map类型中,根据key取值
  30. func (j *Json) Get(key string) *Json
  31. 7. 更新json
  32. func (j *Json) Del(key string)
  33. func (j *Json) Set(key string, val interface{})
  34. 8. 序列化
  35. func (j *Json) Encode() ([]byte, error)
  36. func (j *Json) EncodePretty() ([]byte, error) // 带缩进

2.2. 案例

测试的 Json 字符串如下

  1. {
  2. "deploy_type":"task",
  3. "uniqid":"task-01",
  4. "labels":{
  5. "deploy_type":"db"
  6. },
  7. "callback_url":"https://xxx.xxx.xxx",
  8. "tasks":[
  9. {
  10. "cluster_type":"vm_cluster",
  11. "deploy_type":"vm_cluster",
  12. "action":"create",
  13. "labels":{
  14. "deploy_type":"cluster"
  15. },
  16. "uniqid":"cluster01",
  17. "name":"cluster01",
  18. "options":{
  19. "cadvisor":true
  20. }
  21. }
  22. ]
  23. }

2.2.1. 取值

  1. func main() {
  2. sJson, err := simplejson.NewJson([]byte(str))
  3. if err != nil {
  4. fmt.Printf("New json failed, err:%s\n", err.Error())
  5. return
  6. }
  7. // labels
  8. res1 := sJson.Get("labels").Get("deploy_type").MustString("null")
  9. tmp1, _ := json.Marshal(sJson.Get("tasks").MustArray()[0]) // 返回值为 interface,需要重新序列化
  10. tmp2, _ := simplejson.NewJson(tmp1)
  11. res2 := tmp2.Get("labels").Get("deploy_type").MustString()
  12. fmt.Printf("res1:%s,res2:%s\n", res1, res2)
  13. }

2.2.2 修改值

  1. func main() {
  2. sJson, err := simplejson.NewJson([]byte(str))
  3. if err != nil {
  4. fmt.Printf("New json failed, err:%s\n", err.Error())
  5. return
  6. }
  7. // 删除值
  8. sJson.Del("tasks") // 删除task字段
  9. res1, _:= sJson.EncodePretty()
  10. fmt.Println(string(res1))
  11. // 修改值
  12. sJson.Set("labels", false) // 修改labels字段
  13. res2, _:= sJson.EncodePretty()
  14. fmt.Println(string(res2))
  15. }