摘要://handler/parse_json_request package handler import ( "encoding/json" "fmt" "net/http" ) type Person struct { Name string Age int } func DisplayPersonHandler(w http.ResponseWriter, r *http.Request) { var p Person // 將請求體中的 JSON 數據解析到結構體中 // 發生錯誤,返回400 錯誤碼 err := json.NewDecoder(r.Body).Decode(&p) if err。那麼針對 Web 編程我們其實只要關注怎麼從 HTTP 請求的 Body 中讀取到 JSON 數據,以及如何將要返回給客戶端的數據以 JSON 格式寫入到 HTTP 響應中。

現在無論是網站、 App 、小程序還是移動端 H5 頁面應用,都是採用前端與後端單獨部署,相互之間以 API 接口交互的形式構建而成的。因爲在結合可讀性、編碼數據大小和開發者使用難度上都 JSON 格式是一個比較好的選擇,所以接口的數據格式通常都採用 JSON ,即前端在發送 POSTPUTPATCH 請求添加,更改數據時會把數據以 JSON 格式放到請求的 Body 中。而後端則是所有數據都會以 JSON 格式返回。

關於 JSON 可讀性、編碼數據大小和開發者使用難度上,因爲其可讀性不如 XML 結構,但是數據量小,用程序操作起來更方便。對比 Protobuf 來說, Protobuf 編碼速度、編碼後數據大小比 JSON 都要好,但是用程序操作起來沒有 JSON 方便簡單,編碼後的數據是二進制格式的,易讀性完全沒有。所以整體來說 JSON 是一個各個方面都不錯更容易被所有人接受才被廣泛使用的(以上都是個人觀點)。

之前也寫過兩篇關於用 Go 語言解碼和編碼 JSON 數據的文章

那麼針對 Web 編程我們其實只要關注怎麼從 HTTP 請求的 Body 中讀取到 JSON 數據,以及如何將要返回給客戶端的數據以 JSON 格式寫入到 HTTP 響應中。

從請求體讀取JSON數據

關於這部分內容其實在之前的文章 深入學習解析HTTP請求 裏有說過。

我們需要把請求體作爲 json.NewDecoder() 的輸入流,然後將請求體中攜帶的 JSON 格式的數據解析到聲明的結構體變量中

//handler/parse_json_request
package handler

import (
    "encoding/json"
    "fmt"
    "net/http"
)

type Person struct {
    Name string
    Age  int
}

func DisplayPersonHandler(w http.ResponseWriter, r *http.Request) {
    var p Person

    // 將請求體中的 JSON 數據解析到結構體中
    // 發生錯誤,返回400 錯誤碼
    err := json.NewDecoder(r.Body).Decode(&p)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    
    fmt.Fprintf(w, "Person: %+v", p)
}

// router/router.go
indexRouter.HandleFunc("/parse_json_request", handler.ParseJsonRequestHandler)

在命令行裏用 cURL 命令測試我們的程序:

curl -X POST -d '{"name": "James", "age": 18}' \
     -H "Content-Type: application/json" \
     http://localhost:8000/index/parse_json_request

把JSON數據寫入響應

與上面相反,將返回數據以 JSON 格式寫入響應時,我們調用 json.NewEncodeer(w).Encode(&v) ,用響應體作爲輸入流創建 JSON 編碼器,然後使用其 Encode() 方法將數據編碼爲 JSON 格式並寫入響應體。

// handler/write_json_response
package handler

import (
    "encoding/json"
    "net/http"
)

type User struct {
    FirstName string `json:"firstname"`
    LastName  string `json:"lastname"`
    Age       int    `json:"age"`
}

func WriteJsonResponseHandler(w http.ResponseWriter, r *http.Request) {
    p := User{
        FirstName: "John",
        LastName:  "Doe",
        Age:       25,
    }
  // Set response header
    w.Header().Set("Content-Type", "application/json")
    err := json.NewEncoder(w).Encode(&p)
    if err != nil {
        //... handle error
    }
}

// router/router.go
indexRouter.HandleFunc("/get_json_response", handler.WriteJsonResponseHandler)

重啓服務器後在命令行裏用 cURL 命令測試我們的程序:

curl -X GET http://localhost:8000/index/get_json_response
{"firstname":"John","lastname":"Doe","age":25}

今天的內容很簡單,源碼已經上傳,公衆號回覆gohttp12獲取文中源代碼的下載鏈接。

前文回顧

深入學習用Go編寫HTTP服務器

Go Web編程--應用ORM

Go Web 編程--超詳細的模板庫應用指南

Go Web編程--使用Go語言創建靜態文件服務器

Go Web編程--給自己寫的服務器添加錯誤和訪問日誌

相關文章