因為在猶豫要不要用 BeeGo 寫 blog 網站了,所以有點不知道要寫什麼。
今天來介紹回應格式,預設的回應格式是 HTML,所以指定模版以後就搞定了。如果要輸出 JSON / JSONP / XML / YAML 的話,該怎麼使用呢?
使用上其實蠻簡單的,主要呼叫這幾個 API 即可:
下面借網站上的範例來說明
type mystruct struct {
FieldOne string `json:"field_one"`
}
// 輸出 JSON
func (this *AddController) Get() {
mystruct := { ... }
this.Data["json"] = &mystruct
this.ServeJSON()
// this.ServeXML()
// this.ServeJSONP()
// this.ServeYAML()
}
讓我們追蹤程式,了解一下 BeeGo 是怎麼實作的。
從 this.ServeJSON() 可以看到 ServeJSON() 應該是由 Controller 所提供的。而 Controller 可以在 beego 原始碼的 controller.go 找到。
裏面的 ServeJSON()
// ServeJSON sends a json response with encoding charset.
func (c *Controller) ServeJSON(encoding ...bool) {
var (
hasIndent = BConfig.RunMode != PROD
hasEncoding = len(encoding) > 0 && encoding[0]
)
c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding)
}
可以看到,他會判斷 RunMode 來決定是否要增加縮排來提升可讀性,接著就使用 Conntroller 裡的 context 物件裡的 Output 去輸出 JSON。
Output.JSON() 可以在 context/output.go 找到 JSON() 這個函式。
func (output *BeegoOutput) JSON(data interface{}, hasIndent bool, encoding bool) error {
output.Header("Content-Type", "application/json; charset=utf-8")
var content []byte
var err error
if hasIndent {
content, err = json.MarshalIndent(data, "", " ")
} else {
content, err = json.Marshal(data)
}
if err != nil {
http.Error(output.Context.ResponseWriter, err.Error(), http.StatusInternalServerError)
return err
}
if encoding {
content = []byte(stringsToJSON(string(content)))
}
return output.Body(content)
}
這函式主要是先指定 Content-Type 這個 header 為 application/json,接著使用 json module 對資料做 marshal ,最後再輸出。
其他格式的作法也都大同小異。
這邊順便複習一下 Django REST framework 的作法,DRF 是使用 Renderer 來指定輸出的格式,可以在 settings 裡去指定 DEFAULT_RENDERER_CLASSES ,也可以在個別的 APIView 裡去指定 renderer_classes 。DRF 的作法是比較彈性的,API endpoint 都是一致,但可以使用 format 這個共通的 query parameter 去指定要輸出的格式。
BeeGo 沒有像 DRF 一樣,設定一下就解決,但在程式上還是可以做的到的。