是否有一个包在malang中输入和输出x-www-form-urlencoding

时间:2014-03-22 17:46:06

标签: go marshalling urlencode unmarshalling

我想整理进出x-www-form-urlencoding,类似于你如何使用json或xml。是否有现成的软件包可以执行此操作,或者是否有任何文档如何在不存在的情况下自行实现?

5 个答案:

答案 0 :(得分:14)

gorilla/schema受欢迎且维护良好:

e.g。

func FormHandler(w http.RequestWriter, r *http.Request) {

    err := r.ParseForm()
    if err != nil {
         // handle error
    }
    person := new(Person) // Person being a struct type
    decoder := schema.NewDecoder()

    err = decoder.Decode(person, r.Form)
    if err != nil {
         // handle error
    }

}

goforms也是另一种选择。

2015年5月23日更新:

  • gorilla / schema仍然是我选择的最受支持的map-to-struct软件包之一,POST表单值是一个常见的用例。
  • goji/param也非常扎实,并且具有许多相同的功能。
  • mholt/binding在(IMO)费用稍微复杂一点的API上更具特色。

我已经使用大猩猩/架构几年了,并且没有任何重大问题。我将它与vala结合使用,以便在它们命中数据库之前验证输入(不是零,太短,太长等)。

答案 1 :(得分:6)

我刚刚找到了https://github.com/ajg/form,这正是我想要的。还有https://github.com/gorilla/schema用于严格解码,https://github.com/google/go-querystring用于严格编码。

答案 2 :(得分:2)

https://github.com/google/go-querystring很好,但不支持地图(和地图切片)。

我开始https://github.com/drewlesueur/querystring以获取地图支持。 (它还不支持结构,但欢迎拉取请求。)

答案 3 :(得分:1)

The "github.com/pasztorpisti/qs" package还可以将结构编组到/从查询字符串和POST - ed表单中解组。

示例:

package main

import "fmt"
import "github.com/pasztorpisti/qs"

type Query struct {
    Search     string
    Page       int
    PageSize   int
    Categories []string `qs:"category"`
}

func main() {
    queryStr, err := qs.Marshal(&Query{
        Search:     "my search",
        Page:       2,
        PageSize:   50,
        Categories: []string{"c1", "c2"},
    })
    fmt.Println("Marshal-Result:", queryStr, err)

    var q Query
    err = qs.Unmarshal(&q, queryStr)
    fmt.Println("Unmarshal-Result:", q, err)

    // Output:
    // Marshal-Result: category=c1&category=c2&page=2&page_size=50&search=my+search <nil>
    // Unmarshal-Result: {my search 2 50 [c1 c2]} <nil>
}

此套餐的可能卖点:

  • 结构字段名称在查询字符串中自动显示为snake_case。您不必为结构字段标记添加qs:"field_name"。可以更改此行为。
  • 模块化体系结构,即使对于内置类型(如bool[]byte)也可以替换编组程序和解组程序,并在不修改类型本身的情况下添加对新类型的支持(例如:添加编组和/或time.Time的解组。 Here就是一个例子。
  • 您可以将req选项添加到struct field标记中,以便在解组时使字段成为必需字段。请注意,这是相当验证而不是解组,golang库通常会在两者之间进行分离,但我发现这个选项非常有用,因为它经常需要,它很简单并且读取得很好。对于那些希望避免req并在解组后单独进行验证的人:有一个nil标记选项与默认opt几乎相同(代表&#34) ;可选&#34;)除了当给定字段不在解组查询字符串中时它不初始化nil指针。这样验证器代码可以通过在解组后查找nil指针来检测缺少的字段。
  • qs包可以在实际封送该类型的实例之前判断复杂类型(例如:您的结构)是否可以编组。即使在编组给定类型的实例之后,大多数封送程序包也无法执行此操作!大多数编组程序通过遍历正在编组的对象并仅检查被访问的子对象的类型来检查复杂类型。这意味着如果复杂对象包含一个空的容器(指针,映射或切片),那么容器的项类型甚至不会被检查。在合同中qs遍历复杂对象的类型结构(而不​​是对象本身),同时为类型创建封送器,以便在必须失败的地方失败。请考虑以下代码,其中标准"encoding/json"包成功封送其类型包含非可编组类型的对象:

    package main
    
    import (
        "encoding/json"
        "fmt"
        "reflect"
    
        "github.com/pasztorpisti/qs"
    )
    
    type NonMarshalable func()
    
    func jsonEmptyMap() {
        // Since the container is empty "encoding/json" doesn't examine the type
        // of its items. This results in an unexpected success.
        var m = map[string]NonMarshalable{}
        j, err := json.Marshal(m)
        fmt.Println(string(j), err)
        // Output:
        // {} <nil>
    }
    
    func jsonNonEmptyMap() {
        var m = map[string]NonMarshalable{
            "f": func() {},
        }
        j, err := json.Marshal(m)
        fmt.Println(string(j), err)
        // Output:
        //  json: unsupported type: main.NonMarshalable
    }
    
    func qsEmptyMap() {
        // qs.Marshal fails even if the container is empty because the first step
        // of qs.Marshal fails: It can't create the marshaler object for this type.
        var m = map[string]NonMarshalable{}
        s, err := qs.Marshal(m)
        fmt.Println(s, err)
        // Output:
        //  error getting marshaler for map value type main.NonMarshalable :: unhandled type: main.NonMarshalable
    }
    
    func qsTypeCheck() {
        // You don't even have to try to marshal an object to find out whether its
        // type is marshal-friendly. You can check the type directly. By doing this
        // at startup (e.g.: from init functions) you can avoid delaying runtime
        // errors.
        t := reflect.TypeOf((map[string]NonMarshalable)(nil))
        err := qs.CheckMarshalType(t)
        fmt.Println(err)
        // Output:
        // error getting marshaler for map value type main.NonMarshalable :: unhandled type: main.NonMarshalable
    }
    
    func main() {
        jsonEmptyMap()
        jsonNonEmptyMap()
        qsEmptyMap()
        qsTypeCheck()
    }
    

答案 4 :(得分:1)

net/url 似乎处理得很好:

package main

import (
   "fmt"
   "net/url"
)

func main() {
   {
      m := url.Values{
         "CR": {"\r"}, "LF": {"\n"},
      }
      s := m.Encode()
      fmt.Println(s) // CR=%0D&LF=%0A
   }
   {
      s := "CR=%0D&LF=%0A"
      m, e := url.ParseQuery(s)
      if e != nil {
         panic(e)
      }
      fmt.Printf("%q\n", m) // map["CR":["\r"] "LF":["\n"]]
   }
}