Go 快速入门指南 - JSON

概述

encoding/json 包含了 JSON 相关处理方法。

例子

结构体转为 JSON 字符串

调用 json.Marshal() 方法完成。

package main

import (
    "encoding/json"
    "fmt"
)

type person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
    addr string `json:"addr"` // 该属性转 JSON 时会被忽略
}

func main() {
    tom := person{ // 使用字面量初始化
        Name: "Tom",
        Age:  6,
        addr: "???",
    }

    tomJson, err := json.Marshal(tom)
    if err != nil {
        panic(err)
    }
    fmt.Printf("json.Marshal(tom) = %s\n", tomJson) // 从输出字符串中可以看到,并没有 addr 属性
}

// $ go run main.go
// 输出如下 
/**
  json.Marshal(tom) = {"name":"Tom","age":6}
*/

JSON 字符串转为结构体

调用 json.Unmarshal() 方法完成。

package main

import (
    "encoding/json"
    "fmt"
)

type person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
    addr string `json:"addr"` // 该属性转 json 时会被忽略
}

func main() {
    // 注意: JSON 字符串格式一定要正确,否则会报错
    tomJson := `
{
  "name": "Tom",
  "age": 6,
  "addr": "???"
}
`
    var tom person
    err := json.Unmarshal([]byte(tomJson), &tom)
    if err != nil {
        panic(err)
    }

    // 从输出字符串中可以看到,并没有为 addr 属性赋值
    fmt.Printf("Tom's name is %s, age is %d, addr is %s\n", tom.Name, tom.Age, tom.addr)
}

// $ go run main.go
// 输出如下 
/**
  Tom's name is Tom, age is 6, addr is
*/

输出格式化 JSON 字符串

调用 json.MarshalIndent() 方法完成。

package main

import (
    "encoding/json"
    "fmt"
)

type person struct {
    Name  string   `json:"name"`
    Age   int      `json:"age"`
    Hobby []string `json:"hobby"`
}

func main() {
    tom := person{ // 使用字面量初始化
        Name: "Tom",
        Age:  6,
        Hobby: []string{
            "reading",
            "coding",
            "movie",
        },
    }

    // 前缀符为空字符串,缩进符为两个空格
    formatted, err := json.MarshalIndent(tom, "", "  ")
    if err != nil {
        panic(err)
    }

    fmt.Printf("json.MarshalIndent(tom) = \n%s\n", formatted)
}

// $ go run main.go
// 输出如下 
/**
  json.MarshalIndent(tom) =
  {
    "name": "Tom",
    "age": 6,
    "hobby": [
      "reading",
      "coding",
      "movie"
    ]
  }
*/

忽略零值

通过 omitempty 关键字完成。

package main

import (
    "encoding/json"
    "fmt"
)

type person struct {
    Name  string   `json:"name"`
    Age   int      `json:"age"`
    Hobby []string `json:"hobby,omitempty"` // omitempty 关键字将字段标记为忽略零值
}

func main() {
    tom := person{ // 使用字面量初始化
        Name: "Tom",
        Age:  6,
    }

    // 前缀符为空字符串,缩进符为两个空格
    formatted, err := json.MarshalIndent(tom, "", "  ")
    if err != nil {
        panic(err)
    }

    fmt.Printf("json.MarshalIndent(tom) = \n%s\n", formatted)
}

// $ go run main.go
// 输出如下 
/**
  json.MarshalIndent(tom) =
  {
    "name": "Tom",
    "age": 6
  }
*/

保留零值

某些场景下,需要在输出 JSON 字符串时自动忽略零值,但是在将 JSON 字符串转为目标结构体时,需要保留零值。
可以通过将字段设置为 指针 类型即可。

package main

import (
    "encoding/json"
    "fmt"
)

type person struct {
    Name     string `json:"name"`
    Age      int    `json:"age"`
    HasMoney *bool  `json:"hasMoney,omitempty"`
}

func main() {
    tomJson := `
{
  "name": "Tom",
  "age": 6,
  "hasMoney": false
}
`
    var tom person
    err := json.Unmarshal([]byte(tomJson), &tom)
    if err != nil {
        panic(err)
    }

    fmt.Printf("Tom's name is %s, age is %d, hasMoney is %t\n", tom.Name, tom.Age, *tom.HasMoney)
}

// $ go run main.go
// 输出如下 
/**
  Tom's name is Tom, age is 6, hasMoney is false
*/

忽略公开值

某些场景下,需要将结构体字段设置为公开可导出,但是又不希望 JSON 序列化时输出该字段,
可以使用 - 符号标识。

package main

import (
    "encoding/json"
    "fmt"
)

type person struct {
    Name  string   `json:"name"`
    Age   int      `json:"age"`
    Hobby []string `json:"-"`
}

func main() {
    tom := person{ // 使用字面量初始化
        Name: "Tom",
        Age:  6,
        Hobby: []string{
            "reading",
            "coding",
            "movie",
        },
    }

    // 前缀符为空字符串,缩进符为两个空格
    formatted, err := json.MarshalIndent(tom, "", "  ")
    if err != nil {
        panic(err)
    }

    fmt.Printf("json.MarshalIndent(tom) = \n%s\n", formatted)
}

// $ go run main.go
// 输出如下 
/**
  json.MarshalIndent(tom) =
  {
    "name": "Tom",
    "age": 6
  }
*/

联系我

公众号

go
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!