JSON 序列化和反序列化

    在 Go 中我们主要使用官方的 encoding/json 包对 JSON 数据进行序列化和反序列化,主要使用方法有:

    • 序列化:

    • 反序列化:

      1. func Unmarshal(data []byte, v interface{}) error

    简单例子:

    1. package main
    2. import (
    3. "encoding/json"
    4. "fmt"
    5. )
    6. func main() {
    7. var (
    8. data = `1`
    9. value int
    10. )
    11. err1 := json.Unmarshal([]byte(data), &value)
    12. fmt.Println("Unmarshal error is:", err1)
    13. fmt.Printf("Unmarshal value is: %T, %d \n", value, value)
    14. value2, err2 := json.Marshal(value)
    15. fmt.Println("Marshal error is:", err2)
    16. fmt.Printf("Marshal value is: %s \n", string(value2))
    17. }
    1. Unmarshal error is: <nil>
    2. Unmarshal value is: int, 1
    3. Marshal error is: <nil>
    4. Marshal value is: 1

    在这个例子中,我们使用 UnmarshalMarshal 将一个整数的 JSON 二进制转化为 go int 数据。

    例如:我们把上面例子中 value 类型由 int 修改为 string 后再次运行代码,你将得到 Unmarshal error is: json: cannot unmarshal number into Go value of type string 的错误提醒。

    JSON 和 Go 数据类型对照表:

    1. package main
    2. import (
    3. "encoding/json"
    4. "fmt"
    5. )
    6. func main() {
    7. var (
    8. d1 = `false`
    9. v1 bool
    10. )
    11. json.Unmarshal([]byte(d1), &v1)
    12. printHelper("d1", v1)
    13. var (
    14. d2 = `2`
    15. v2 int
    16. )
    17. json.Unmarshal([]byte(d2), &v2)
    18. printHelper("d2", v2)
    19. d3 = `3.14`
    20. )
    21. json.Unmarshal([]byte(d3), &v3)
    22. printHelper("d3", v3)
    23. var (
    24. d4 = `[1,2]`
    25. v4 []int
    26. )
    27. json.Unmarshal([]byte(d4), &v4)
    28. printHelper("d4", v4)
    29. var (
    30. d5 = `{"a": "b"}`
    31. v5 map[string]string
    32. v6 interface{}
    33. )
    34. json.Unmarshal([]byte(d5), &v5)
    35. printHelper("d5", v5)
    36. json.Unmarshal([]byte(d5), &v6)
    37. printHelper("d5(interface{})", v6)
    38. }
    39. func printHelper(name string, value interface{}) {
    40. fmt.Printf("%s Unmarshal value is: %T, %v \n", name, value, value)
    41. }

    运行代码我们可以得到如下输出结果:

    除了使用上面基础数据外,对于那些比较复杂的数据集合(Object),我们还可以使用自定义数据类型 struct 来转化。

    • Go 中关于 JSON 转化字段名的对应语法为:
    1. Field int `json:"myName"`
    • 如果我们想忽略那些空值的字段,我们可以使用 omitempty 选项:
    1. Field int `json:"myName,omitempty"`
    • 如果我们想忽略特定字段:
    1. Field int `json:"-"`

    组合示例:

    1. type A struct {
    2. A int `json:"k"`
    3. B string `json:"b,omitempty"`
    4. C float64 `json:"-"`
    5. }

    假如我们有这样一段 JSON 数据,它表示一个学生的考试成绩,下面我们就来看看在 Go 中如何序列化和反序列化。

    • 数据准备:
    • 反序列化:
    1. package main
    2. import (
    3. "encoding/json"
    4. "fmt"
    5. "io/ioutil"
    6. )
    7. type Result struct {
    8. Name string `json:"name"`
    9. Score float64 `json:"score"`
    10. }
    11. type Student struct {
    12. Id int `json:"id"`
    13. Name string `json:"name"`
    14. Results []Result `json:"results"`
    15. func main() {
    16. dat, _ := ioutil.ReadFile("data.json")
    17. var s Student
    18. json.Unmarshal(dat, &s)
    19. fmt.Printf("Student's result is: %v\n", s)
    20. }
    1. Student's result is: {1 小红 [{语文 90} {数学 100}]}
    • 序列化:
    1. package main
    2. import (
    3. "encoding/json"
    4. "io/ioutil"
    5. )
    6. type Result struct {
    7. Name string `json:"name"`
    8. Score float64 `json:"score"`
    9. }
    10. type Student struct {
    11. Id int `json:"id"`
    12. Name string `json:"name"`
    13. Results []Result `json:"results"`
    14. }
    15. func main() {
    16. s := Student{
    17. Id: 1,
    18. Name: "小红",
    19. Results: []Result{
    20. Result{
    21. Name: "语文",
    22. Score: 90,
    23. },
    24. Result{
    25. Name: "数学",
    26. Score: 100,
    27. },
    28. },
    29. }
    30. dat, _ := json.Marshal(s)
    31. ioutil.WriteFile("data2.json", dat, 0755)
    32. }

    当我们运行代码后,打开 data2.json 文件,将看到如下内容:

    1. {
    2. "id": 1,
    3. "name": "小红",
    4. "results": [
    5. {
    6. "name": "语文",
    7. "score": 90
    8. },
    9. {
    10. "name": "数学",
    11. "score": 100
    12. }
    13. }