20.1 JSON-JSON接口以及在Go语言中使用JSON_json数据接口

1. 简介

JSON即JavaScript对象表示法(JavaScript Object Notation),是一种用于存储和交换数据的格式,是一种可供人类阅读和理解的纯文本格式。

JSON既可以键值对的形式,也可以数组的形式,表示数据。

JSON最初是JavaScript的一个子集,但现在已然独立,为大多数语言所支持。

JSON已经取代XML,成为互联网上存储和交换数据的事实标准。

JSON以下面这种形式描述对象(一系列键值对组合):

  • {
  •         "name": "George",

        "age": 40,

        "children": ["Bea", "Fin"]

       }

2. JSON接口

近年来,互联网上出现了很多卓越的JSON格式的API (Application Programming Interface,应用编程接口)。

借助这些API,应用程序可以从作为数据交换平台的互联网上,获得海量的有关任何主题的数据。

API令应用开发者无须连接到数据库,就能请求并使用各种形式的数据资源。

  • 例如下面的JSON数据来自Dark Sky天气预报服务系统,通过json格式字符串描述了经纬度、时区、温度等内容。
    • {"latitude": 42.3601, "longitude": -71.0589, "timezone": "America/New_York",
    •  "currently": {"time": 1509993277, "summary": "Drizzle", "icon": "rain",
    •                      "nearestStormDistance": 0, "precipIntensity": 0.0089, ...},
    •  "minutely": {"summary": "Light rain stopping in 13 min., starting again 30 min. later.",
    •                      "icon": "rain", "data": [{...}, ...]},
    • "hourly": {"summary": ... }, ... }

 3. 在Go语言中使用JSON

Go语言标准库通过encoding/json包提供对JSON数据的编码和解码操作。

JSON编码,即将Go语言数据类型的变量转换为JSON格式的字符串

  • 定义结构体类型
    • type Person struct { ... },结构体的字段名对应json的“键”
  • 创建结构体变量
    • p := Person{ ... }
  • 将结构体变量编码为JSON格式的字节切片 
    • jb, err := json.Marshal(p)
  • 将JSON格式的字节切片转换JSON格式的字符串 
    • js := string(jb) 

  1. // 创建结构体
  2. // 结构体可将多个不同类型的数据组织在一起,是一种绝佳的数据封装形式
  3. package main
  4. import "fmt"
  5. type person struct {
  6.     name string
  7.     age int
  8.     hobbies []string
  9. }
  10. func main() {
  11.     p := person{
  12.         name: "George",
  13.         age: 40,
  14.         hobbies: []string{"Cycling", "Cheese", "Techno"},
  15.     }
  16.     fmt.Printf("%+v\n", p)
  17. }
  18. // 打印输出:
  19. {name:George age:40 hobbies:[Cycling Cheese Techno]}

 

  1. // 将结构体编码为JSON字符串
  2. // json.Marshal string
  3. // 结构体 -------------> JSON字节切片 ------> JSON字符串
  4. package main
  5. import (
  6.     "encoding/json"
  7.     "fmt"
  8.     "log"
  9. )
  10. // Person with name, age and hobbies
  11. type Person struct {
  12.     Name string
  13.     Age int
  14.     Hobbies []string
  15. }
  16. func main() {
  17.     p := Person{
  18.         Name: "George",
  19.         Age: 40,
  20.         Hobbies: []string{
  21. "Cycling", "Cheese", "Techno"},
  22.     }
  23.     fmt.Printf("%+v\n", p)
  24. jb, err := json.Marshal(p) //将结构体变量编码为JSON格式的字节切片
  25.     if err != nil {
  26.         log.Fatal(err)
  27.     }
  28.     js := string(jb) // 将json字节切片转换为json字符串
  29.     fmt.Println(js)
  30. }
  31. // 打印输出:
  32. {Name:George Age:40 Hobbies:[Cycling Cheese Techno]}
  33. {"Name":"George","Age":40,"Hobbies":["Cycling","Cheese","Techno"]}

 

默认情况下,JSON字符串中的分别取自结构体中的字段名字段值(大小写敏感)。

  • type Person struct {
  •     Name    string
  •     Age     int
  •     Hobbies []string
  • }
  • {"Name":"George","Age":40,"Hobbies":["Cycling","Cheese","Techno"]}

如果为结构体字段指定了JSON标签,则以标签文本作为JSON字符串的键。

  • type Person struct {

  // 标签是以反引号包围的

    Name    string   `json:"name"`

    Age     int      `json:"age"`

    Hobbies []string `json:"hobbies"`

}

        {"name":"George","age":40,"hobbies":["Cycling","Cheese","Techno"]}

  1. // 使用JSON标签
  2. // 默认情况下,JSON字符串中的键和值分别取自结构体中的字段名和字段值,但
  3. // 如果为结构体中的字段指定了JSON标签,则以标签文本作为JSON字符串的键
  4. //
  5. // type 结构体 struct {
  6. // 字段1 类型1 `json:"键1"`
  7. // 字段2 类型2 `json:"键2"`
  8. // ...
  9. // 字段n 类型n `json:"键n"`
  10. // }
  11. package main
  12. import (
  13.     "encoding/json"
  14.     "fmt"
  15.     "log"
  16. )
  17. // Person with name, age and hobbies
  18. type Person struct {
  19.     Name string `json:"name"`
  20.     Age int `json:"age"`
  21.     Hobbies []string `json:"hobbies"`
  22. }
  23. func main() {
  24.     p := Person{
  25.         Name: "George",
  26.         Age: 40,
  27.         Hobbies: []string{
  28. "Cycling", "Cheese", "Techno"},
  29.     }
  30.     fmt.Printf("%+v\n", p)
  31. jb, err := json.Marshal(p)
  32.     if err != nil {
  33.         log.Fatal(err)
  34.     }
  35.     js := string(jb)
  36.     fmt.Println(js)
  37. }
  38. // 打印输出:
  39. {Name:George Age:40 Hobbies:[Cycling Cheese Techno]}
  40. {"name":"George","age":40,"hobbies":["Cycling","Cheese","Techno"]}

默认情况下,结构体中的零值字段也会被编码到JSON字符串中。

  • type Person struct {
  •     Name    string   `json:"name"`
  •     Age     int      `json:"age"`
  •     Hobbies []string `json:"hobbies"`
  • }

p:= Person{} // 使用默认零值初始化

    • 通过json.Marshal(p)函数将结构体解析为json字符如下:

{"name":"","age":0,"hobbies":[]}

在JSON标签中使用"omitempty"关键字,令编码器在编码时忽略零值字段。

  • type Person struct {
  •     Name    string   `json:"name,omitempty"`
  •     Age     int      `json:"age,omitempty"`
  •     Hobbies []string `json:"hobbies,omitempty"`
  • }
  • {}

 

  1. // 忽略空字段
  2. // 默认情况下,结构体中的零值字段也会被编码到JSON字符串中,除非在其JSON
  3. // 标签中使用了"omitempty"关键字,指示编码器在编码的过程中忽略零值字段
  4. package main
  5. import (
  6.     "encoding/json"
  7.     "fmt"
  8.     "log"
  9. )
  10. // Person with name, age and hobbies
  11. type Person struct {
  12.     Name string `json:"name,omitempty"`
  13.     Age int `json:"age,omitempty"`
  14.     Hobbies []string `json:"hobbies,omitempty"`
  15. }
  16. func main() {
  17.     p := Person{}
  18.     fmt.Printf("%+v\n", p)
  19.     jb, err := json.Marshal(p)
  20.     if err != nil {
  21.         log.Fatal(err)
  22.     }
  23.     js := string(jb)
  24.     fmt.Println(js)
  25. }
  26. // 打印输出:
  27. {Name: Age:0 Hobbies:[]}
  28. {}