@@ -1,58 +0,0 @@ 23.JSON处理 | 凤凰涅槃进阶之路

23.JSON处理

Abel sun2023年1月6日约 1633 字大约 5 分钟

23.JSON处理

1,编码json

JSON(JavaScript Object Notation)是一种比XML更轻量级的数据交换格式,在易于人们阅读和编写的同时,也易于程序解析和生成。尽管JSON是JavaScript的一个子集,但JSON采用完全独立于编程语言的文本格式,且表现为键/值对集合的文本描述形式(类似一些编程语言中的字典结构),这使它成为较为理想的,跨平台,跨语言的数据交换语言。

{
 "Company":"itcast",
 "Subjects":[
  "Go",
  "C++",
  "Python",
  "Test"
 ],
 "Isok":true,
 "Price":666
}

开发者可以用JSON传输简单的字符串,数字,布尔值,也可以传输一个数组,或者一个更复杂的复合结构。在web开发领域中,JSON被广泛应用于web服务端程序和客户端之间的数据通信。

Go语言内建对JSON的支持。使用Go语言内置的encoding/json标准库,开发者可以轻松使用Go程序生成和解析JSON格式的数据。

JSON官方网站:http://www.json.orgopen in new window 在线格式化:http://www.json.cnopen in new window

1,通过结构体生成JSON

使用json.Marshal()函数可以对一组数据进行JSON格式的编码。 json.Marshal()函数的声明如下:

 func Marshal(v interface{}) ([]byte, error)

还有一个格式化输出:

 // MarshalIndent 很像 Marshal,只是用缩进对输出进行格式化
 func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)

1,示例代码

package main

import (
 "encoding/json"
 "fmt"
)

/*
{
    "Company":"itcast",
    "Subjects":[
        "Go",
        "C++",
        "Python",
        "Test"
    ],
    "Isok":true,
    "Price":666.66
}
*/

type It struct {
 Company  string  //注意变量名称必须是大写开头
 Subjects []string
 Isok     bool
 Price    float64
}

func main() {
 //定义一个结构体变量,同时初始化
 s := It{"itcast", []string{"Go", "C++", "Python", "Test"}, true, 666.66}
 //根据内容生成json文本的过程,叫编码
 //通过json文本解析成内容的过程,叫解码
 //buf, err := json.Marshal(s)
 //以上定义方式输出结果: buf =  {"Company":"itcast","Subjects":["Go","C++","Python","Test"],"Isok":true,"Price":666.66}

 buf, err := json.MarshalIndent(s, "", " ") //格式化编码
 if err != nil {
  fmt.Println("err = ", err)
  return
 }
 fmt.Println("buf = ", string(buf))

}

输出结果:

$ go run 11_通过结构体生成json.go
buf =  {
 "Company": "itcast",
 "Subjects": [
  "Go",
  "C++",
  "Python",
  "Test"
 ],
 "Isok": true,
 "Price": 666.66
}

2,几个技巧

我们看到上面的输出字段名的首字母都是大写的,如果你想用小写的首字母怎么办呢?把结构体的字段名改成首字母小写的?JSON输出的时候必须注意,只有导出的字段(首字母是大写)才会被输出,如果修改字段名,那么就会发现什么都不会输出,所以必须通过struct tag定义来实现。

针对JSON的输出,我们在定义struct tag的时候需要注意的几点是:

  • 字段的tag是”-“,那么这个字段不会输出到JSON
  • tag中带有自定义名称,那么这个自定义名称会出现在JSON的字段名中
  • tag中如果带有”omitempty”选项,那么如果该字段值为空,就不会输出到JSON串中
  • 如果字段类型是bool, string, int, int64等,而tag中带有”,string”选项,那么这个字段在输出到JSON的时候会把该字段对应的值转换成JSON字符串
package main

import (
 "encoding/json"
 "fmt"
)

type It struct {
 Company  string   `json:"company"` //二次编码,可以将变量名称转为小写
 Subjects []string `json:"-"`       //表示这个字段不会输出打印
 Isok     bool     `json:",string"` //表示先转换为字符串,再输出到屏幕
 Price    float64  `json:"price, omitempty"` //如果Price为空,则不输出到json串当中
}

func main() {
 //定义一个结构体变量,同时初始化
 s := It{"itcast", []string{"Go", "C++", "Python", "Test"}, true, 666.66}
 //根据内容生成json文本的过程,叫编码
 //通过json文本解析成内容的过程,叫解码
 //buf, err := json.Marshal(s)
 //以上定义方式输出结果: buf =  {"Company":"itcast","Subjects":["Go","C++","Python","Test"],"Isok":true,"Price":666.66}

 buf, err := json.MarshalIndent(s, "", " ") //格式化编码
 if err != nil {
  fmt.Println("err = ", err)
  return
 }
 fmt.Println("buf = ", string(buf))

}

输出结果:

$ go run 11_通过结构体生成json.go
buf =  {
 "company": "itcast",
 "Isok": "true",
 "Price": "666.66"
}

2,通过map生成json

package main

import (
 "encoding/json"
 "fmt"
)

func main() {
 //创建一个map
 m := make(map[string]interface{}, 4)
 m["Company"] = "itcast"
 m["Subjects"] = []string{"Go", "C++", "Python", "Test"}
 m["isok"] = true
 m["price"] = 666.666

 //编码成json
 //result, err := json.Marshal(m)
 result, err := json.MarshalIndent(m, "", " ")
 if err != nil {
  fmt.Println("err = ", err)
  return
 }
 fmt.Println("result = ", string(result))

}

2,解码json

可以使用json.Unmarshal()函数将JSON格式的文本解码为Go里面预期的数据结构。

json.Unmarshal()函数的原型如下:

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

该函数的第一个参数是输入,即JSON格式的文本(比特序列),第二个参数表示目标输出容器,用于存放解码后的值。

1,json解析为结构体

package main

import (
 "encoding/json"
 "fmt"
)

type It struct {
 Company  string   `json:"company"`
 Subjects []string `json:"subjects"`
 Isok     bool     `json:"isok"`
 Price    float64  `json:"price"`
}

func main() {
 jsonbuf := `
 {
 "company": "itcast",
 "subjects": [
  "Go",
  "C++",
  "Python",
  "Test"
 ],
 "isok": true,
 "price": 666.66
}`

 var tmp It
 err := json.Unmarshal([]byte(jsonbuf), &tmp)
 if err != nil {
  fmt.Println("err = ", err)
  return
 }
 //fmt.Println("tmp = ", tmp)
 fmt.Printf("tmp = %+v\n", tmp) //以详细格式输出

 //如果不想要某些字段输出,那么只需要在定义结构体的时候略掉即可
 type It1 struct {
  Subjects []string `json:"subjects"`
 }
 var tmp1 It1
 err = json.Unmarshal([]byte(jsonbuf), &tmp1)
 if err != nil {
  fmt.Println("err = ", err)
  return
 }

 fmt.Printf("tmp1 = %+v\n", tmp1) //以详细格式输出

}

2,json解析为map

package main

import (
 "encoding/json"
 "fmt"
)

func main() {
 jsonbuf := `
 {
 "company": "itcast",
 "subjects": [
  "Go",
  "C++",
  "Python",
  "Test"
 ],
 "isok": true,
 "price": 666.66
}`
 //创建一个map

 m := make(map[string]interface{}, 4)
 err := json.Unmarshal([]byte(jsonbuf), &m)
 if err != nil {
  fmt.Println("err = ", err)
  return
 }
 fmt.Printf("m = %+v\n", m) //以详细格式输出

 // var str string
 // str = string(m["company"])
 // fmt.Println("str = ", str) //err,无法转换类型

 //类型断言
 for key, value := range m {
  switch data := value.(type) {
  case string:
   fmt.Printf("map[%s]的类型为string,value = %s\n", key, data)
  case bool:
   fmt.Printf("map[%s]的类型为bool,value = %v\n", key, data)
  case float64:
   fmt.Printf("map[%s]的类型为float64,value = %v\n", key, data)
  // case []string:
  //  fmt.Printf("map[%s]的类型为[]string,value = %v\n", key, data) //不会打印结果
  case []interface{}:
   fmt.Printf("map[%s]的类型为[]interface{},value = %v\n", key, data) //接着还可以对其进行迭代打印

  }
 }
}

运行结果:

$ go run 14_json解析成map.go
m = map[company:itcast subjects:[Go C++ Python Test] isok:true price:666.66]
map[company]的类型为string,value = itcast
map[subjects]的类型为[]interface{},value = [Go C++ Python Test]
map[isok]的类型为bool,value = true
map[price]的类型为float64,value = 666.66
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.9.1