Go 编程 | 连载 29 - Go 与 JSON

2022-09-28 16:14:20 浏览数 (1)

本文紧接 Go 编程 | 连载 28 - Go 与 JSON

二、Go 与 JSON 的格式映射

在序列化和反序列化时需考虑 JavaScript 和 Go 表示数据类型的方式,Go 是静态强类型语言,JavaScript 是动态弱类型语言。

Go 中声明变量是需要声明数据类型的,即使不声明数据类型 Go 也会在编译器自动判断数据类型,而 JavaScript 则是在运行时才会判断数据类型。 JSON 的数据格式与 JavaScript 相同,JSON 可使用的格式有如下几种:

  • Boolean
  • Number
  • String
  • Array
  • Object
  • Null

但是这些数据类型不会自动映射到 Go 中的数据类型,需要通过 encoding/json 包执行显示的类型转换,JSON 和 Go 中数据类型之间的对应关系如下:

JSON 类型

Go 类型

String

string

Boolean

bool

Number

float64

Array

[]interface{}

Object

mapstringinterface{}

Null

nil

代码语言:javascript复制
package main

import (
   "encoding/json"
   "fmt"
   "log"
)

//noinspection ALL
func main() {

   jsonString := `{"name": "stark", "is_vip": "true"}`

   u := User{}

   err := json.Unmarshal([]byte(jsonString), &u)

   if err != nil {
      log.Fatal(err)
   }
   fmt.Println(u)

}

type User struct {
   Name string `json:"name"`
   IsVip bool `json:"is_vip"`
}

执行上述代码,输出结果如下:

代码语言:javascript复制
2022/09/01 11:41:45 json: cannot unmarshal string into Go struct field User.is_vip of type bool

上述代码反序列化过程中, Go 会将字符串格式的 true 转换为 bool 类型的 true,因此转换失败导致程序停止。

在进行反序列化时要注意 JavaScript 和 Go 之间的类型对应关系,如果转换时类型不对应则会导致错误。

三、处理 HTTP 收到的 JSON 格式数据

在 Go 语言中通过 HTTP 请求收到的 JSON 数据是以流的形式接收的,既不是字符串也不是字节切片,因此需要通过 encoding/json 标准库中的另一个函数 New.Decoder 来进行解码。

我们通过 Gin 框架快速创建一个返回 JSON 格式的 API,使用 net/http 调用这个 API 获取到 JSON 数据,然后将 JSON 数据转换成结构体实例化对象。

首先新建一个 gin-quickstart 项目,然后通过命令行安装 Gin 框架

代码语言:javascript复制
go get -u github.com/gin-gonic/gin

新建 main.go 文件,添加如下代码:

代码语言:javascript复制
package main

// 导入 gin 依赖
//noinspection ALL
import (
   "github.com/gin-gonic/gin"
   "net/http"
)

//noinspection ALL
func main(){

   // 创建路由 engine
   r := gin.Default()
   
   // 创建路由,绑定 handler 函数
   r.GET("/json", ResponseJsonHandler)

   // 启动,绑定端口
   r.Run(":8080")

}

func ResponseJsonHandler (c *gin.Context) {
   d := Data{
      Msg:  "你好 JSON",
      Code: 20000,
   }

   c.JSON(http.StatusOK, d)
}

type Data struct {
   Msg string `json:"msg"`
   Code int `json:"code"`
}

运行 main.go 文件,此时我们就已经搭建了一个 HTTP 服务器,在浏览器中访问 http://localhost:8080/json 可以获取如下响应

接着我们另外一个项目中新建一个 Go 文件,输入如下代码:

代码语言:javascript复制
package main

//noinspection ALL
import (
   "encoding/json"
   "fmt"
   "log"
   "net/http"
)

//noinspection ALL
func main() {

   data := Data{}
   
   // 访问 /json API
   res, err := http.Get("http://localhost:8080/json")

   if err != nil {
      log.Fatal(err)
   }
   
   fmt.Println(res)

   defer res.Body.Close()

   // 处理 JSON 流,将其数据赋值到一个结构体实例化对象 data 上 
   err = json.NewDecoder(res.Body).Decode(&data)

   if err != nil {
      log.Fatal(err)
   }

   fmt.Printf("% vn", data)
   fmt.Printf("%Tn", data)
}

type Data struct {
   Msg string `json:"msg"`
   Code int `json:"code"`
}

执行上述代码,输出结果如下:

代码语言:javascript复制
&amp;{200 OK 200 HTTP/1.1 1 1 map[Content-Length:[34] Content-Type:[application/json; charset=utf-8] Date:[Thu, 01 Sep 2022 17:29:25 GMT]] 0xc00015e400 34 [] false false map[] 0xc00017e000 <nil>}
{Msg:你好 JSON Code:20000}
main.Data

0 人点赞