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

1.2. json序列化

序列化中需要注意的点:

  • 因为是调用 json.Mashal() ,如果结构体字段使用小写将因为不可导出,而无法完成序列化。
  • json.Mashal()可以接收指针,因此实际操作中,都是传递指针而不是值
  • 如果要对结构体中字段名和json中不一致,需要在结构体定义时指定json中显示的名称
  • 1.2.1. 序列化基本案例

  • Id和Name有明确指定 json 序列化后的字段名,因此按小写显示
  • Hobby中的describe字段小写开头,因此不可导出,在json序列化后的结果中不可见
  • 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 main
    import (
    	"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 main
    import (
    	"encoding/json"
    	"fmt"
    type User struct {
    	Name  string		`json:"name"`
    	Class []string		`json:"class"`
    func main()  {
    	str := `{"10001": {"name": "张三", "class": ["物理","化学","生物"]}}`
    	var user01 map[string]User
    	if 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.go
    type:map[string]main.User, value:map[10001:{张三 [物理 化学 生物]}]
    

    1.3.2. 使用空接口接收数据

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

    package main
    import (
    	"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.go
    type: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) int
        func (j *Json) MustString(args ...string) string
        func (j *Json) MustFloat64(args ...float64) float64
        func (j *Json) MustBool(args ...bool) bool
        func (j *Json) MustStringArray(args ...[]string) []string
        func (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) *Json
    7.  更新json
        func (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
    	// 取labels
    	res1 := 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))
    复制代码
  • 私信
  •