1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Gin 框架綁定 JSON 參數(shù)使用 jsoniter

        共 4905字,需瀏覽 10分鐘

         ·

        2021-09-18 13:53

        Gin 框架中,處理 JSON 格式的參數(shù)綁定時,默認采用的標準包 encoding/json,然而標準包不能滿足我們的一些要求,比如兼容字符串整型、PHP 空數(shù)組、時間格式等。

        Gin 框架中,處理 JSON 格式的參數(shù)綁定時,默認采用的標準包 encoding/json,然而標準包不能滿足我們的一些要求,比如兼容字符串整型、PHP 空數(shù)組、時間格式等。

        最簡單的方式

        開發(fā) API 時,需要用到 ShouldBindJSON 綁定傳入的參數(shù)到結(jié)構(gòu)體:

        // github.com/gin-gonic/[email protected]/context.go:643// ShouldBindJSON is a shortcut for c.ShouldBindWith(obj, binding.JSON).func (c *Context) ShouldBindJSON(obj interface{}) error {    return c.ShouldBindWith(obj, binding.JSON)}

        Gin 默認采用 encoding/json 包:

        // github.com/gin-gonic/[email protected]/internal/json/json.go// +build !jsoniterpackage jsonimport "encoding/json"var (    // Marshal is exported by gin/json package.    Marshal = json.Marshal    // Unmarshal is exported by gin/json package.    Unmarshal = json.Unmarshal    // MarshalIndent is exported by gin/json package.    MarshalIndent = json.MarshalIndent    // NewDecoder is exported by gin/json package.    NewDecoder = json.NewDecoder    // NewEncoder is exported by gin/json package.    NewEncoder = json.NewEncoder)

        同時我們看到還支持了 jsoniter

        // github.com/gin-gonic/[email protected]/internal/json/jsoniter.go// +build jsoniterpackage jsonimport "github.com/json-iterator/go"var (    json = jsoniter.ConfigCompatibleWithStandardLibrary    // Marshal is exported by gin/json package.    Marshal = json.Marshal    // Unmarshal is exported by gin/json package.    Unmarshal = json.Unmarshal    // MarshalIndent is exported by gin/json package.    MarshalIndent = json.MarshalIndent    // NewDecoder is exported by gin/json package.    NewDecoder = json.NewDecoder    // NewEncoder is exported by gin/json package.    NewEncoder = json.NewEncoder)

        那我們怎么才能使用到 jsoniter 呢?源碼中已經(jīng)明確了編譯 tag:

        所以,我們只需在編譯時帶上這個 tag 就可以了,例如:

        go build -tags=jsoniter main.go// 或者go run -tags=jsoniter main.go

        自定義的方式

        Gin 框架支持的 jsoniter 是默認配置 jsoniter.ConfigCompatibleWithStandardLibrary。當我們需要其他配置或添加一些自定義擴展(比如時間處理)時,就難受了。于是我們就要自己動手了~

        翻開源碼,我們能看到 binding.JSON 其實使用的是 jsonBinding{} 這個結(jié)構(gòu)體:

        // github.com/gin-gonic/[email protected]/binding/binding.go:73// These implement the Binding interface and can be used to bind the data// present in the request to struct instances.var (    JSON          = jsonBinding{}    // 其他省略了...)

        翻開 jsonBinding 源碼看看:

        // github.com/gin-gonic/[email protected]/binding/json.gotype jsonBinding struct{}func (jsonBinding) Name() string {    return "json"}func (jsonBinding) Bind(req *http.Request, obj interface{}) error {    if req == nil || req.Body == nil {        return fmt.Errorf("invalid request")    }    return decodeJSON(req.Body, obj)}func (jsonBinding) BindBody(body []byte, obj interface{}) error {    return decodeJSON(bytes.NewReader(body), obj)}

        發(fā)現(xiàn)實現(xiàn)了 BindingBody 這個接口:

        // github.com/gin-gonic/[email protected]/binding/binding.go:36// Binding describes the interface which needs to be implemented for binding the// data present in the request such as JSON request body, query parameters or// the form POST.type Binding interface {    Name() string    Bind(*http.Request, interface{}) error}// BindingBody adds BindBody method to Binding. BindBody is similar with Bind,// but it reads the body from supplied bytes instead of req.Body.type BindingBody interface {    Binding    BindBody([]byte, interface{}) error}

        那接下來就簡單了,我們只要實現(xiàn)了這個接口即可,例如:

        package customimport (    "bytes"    "fmt"    "io"    "net/http"    jsoniter "github.com/json-iterator/go"    "github.com/gin-gonic/gin/binding")// BindingJSON 替換Gin默認的binding,支持更豐富JSON功能var BindingJSON = jsonBinding{}// 可以自定義jsoniter配置或者添加插件var json = jsoniter.ConfigCompatibleWithStandardLibrarytype jsonBinding struct{}func (jsonBinding) Name() string {    return "json"}func (jsonBinding) Bind(req *http.Request, obj interface{}) error {    if req == nil || req.Body == nil {        return fmt.Errorf("invalid request")    }    return decodeJSON(req.Body, obj)}func (jsonBinding) BindBody(body []byte, obj interface{}) error {    return decodeJSON(bytes.NewReader(body), obj)}func decodeJSON(r io.Reader, obj interface{}) error {    decoder := json.NewDecoder(r)    if binding.EnableDecoderUseNumber {        decoder.UseNumber()    }    if binding.EnableDecoderDisallowUnknownFields {        decoder.DisallowUnknownFields()    }    if err := decoder.Decode(obj); err != nil {        return err    }    return validate(obj)}func validate(obj interface{}) error {    if binding.Validator == nil {        return nil    }    return binding.Validator.ValidateStruct(obj)}

        自定義 jsonBinding 已經(jīng)寫好了,可使用有 2 種方式:

        // binding.JSON 替換成自定義的ctx.ShouldBindWith(?ms, binding.JSON)ctx.ShouldBindBodyWith(?ms, binding.JSON)

        上述自定義的方式,還可以用于其他包,不僅限于 iterator。從這個方面體現(xiàn)出了 Gin 框架良好的接口設(shè)計??。


        轉(zhuǎn)自公眾號:




        推薦閱讀


        福利

        我為大家整理了一份從入門到進階的Go學習資料禮包,包含學習建議:入門看什么,進階看什么。關(guān)注公眾號 「polarisxu」,回復 ebook 獲??;還可以回復「進群」,和數(shù)萬 Gopher 交流學習。

        瀏覽 49
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            少妇久久久久久被弄到高潮 | 91国产精品一区 | 69成人免费视频 | 人人草在线视频 | 大胸美女被操网站 | A片在线免费看 | 黄色视频亚洲 | 无码人妻一级毛片免费60岁 | 爆操中出| 伊人网在线视频观看 |