Is there a package to marshal in and out of x-www-form-urlencoding in golang
Asked Answered
K

4

33

I would like to marshal in and out of x-www-form-urlencoding similar to how you can do it with json or xml. Is there an existing package to do this, or are there any documents on how to implement one myself if none exist?

Kicksorter answered 22/3, 2014 at 17:46 Comment(10)
net/url in stdlib does what you want, I believe. Keep in mind there's a solid http client and server standard that have to do these things.Loralorain
ParseQuery returns a map[string][]string, which is very useful, but it does not marshal directly to a struct as 'encoding/json' does.Kicksorter
I have no idea where you got that information. It is incorrect according to the documentation and my experience using it.Loralorain
If you want to argue about it, it would be pretty good to link to the documentation you are getting your information from. For me I was looking at net/url.ParseQuery which returns net/url.Values which is defined as type Values map[string][]string. see more here: golang.org/pkg/net/url/#ParseQueryKicksorter
That makes it a url.Values type, not a map[string][]string -- you can convert between them, but they are not interchangeable. The former has a method that does what you want.Loralorain
I do not see where Values implements an Encoding or Decoding interface, which is what I was asking for. Not a way to parse the string, a way to marshal it.Kicksorter
The link above describes an .Encode() method, which does what I believe you're describing.Loralorain
It does not have Decode, which is a lot harder. You can marshal in, but not out.Kicksorter
What is the difference between Decode and the exact function you linked to?Loralorain
One of them marshals directly into arbitrary structs and the other simply outputs a map[string][]string object. If you really don't understand I would recommend asking a question as opposed to having this conversation in a comments section of a dead question.Kicksorter
B
24

gorilla/schema is popular and well maintained:

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 is also an alternative.

Update May 23rd 2015:

  • gorilla/schema is still my pick as one of the most-supported map-to-struct packages, with POST form values being a common use-case.
  • goji/param is also fairly solid and has many of the same features.
  • mholt/binding is a little more feature packed at the (IMO) expense of a slightly more complex API.

I've been using gorilla/schema for a couple of years now and haven't had any major issues with it. I use it in conjunction with vala for validating inputs (not nil, too short, too long, etc) before they hit the DB.

Blistery answered 22/3, 2014 at 23:12 Comment(2)
Awesome I didn't see goforms, I like that there are are min max and required fields. I might just extend goforms to include an actual default value.Kicksorter
Just want to note that gorilla schema doesn't seems to be well supported. I.e. slices of structs can't be marshalled even though the readme says it can. There is an open ticket for it.Indistinctive
K
9

I just found https://github.com/ajg/form which is exactly what I was looking for. There is also https://github.com/gorilla/schema for strictly decoding and https://github.com/google/go-querystring for strictly encoding.

Kicksorter answered 22/3, 2014 at 18:12 Comment(0)
P
6

net/url seems to handle this just fine:

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"]]
   }
}
Plentiful answered 6/4, 2021 at 20:4 Comment(2)
I think this should be the right answer, as all the other answers do much more than just marshalling and unmarshalling the data (they all parse the content into a predefined struct, which is useful, but not the question asked). If you want to just marshal/unmarshal all the data within the url parameters, this should be the answer.Francium
Agreed, especially true now that the Gorilla project mentioned in the accepted answer is well-and-truly dead.Germinal
B
2

https://github.com/google/go-querystring is good, but doesn't support maps (and slices of maps).

I started https://github.com/drewlesueur/querystring for map support. (It doesn't support structs yet, but pull requests welcome).

Bergess answered 25/5, 2015 at 19:21 Comment(2)
It looks like go-querystring only allows for encoding, not decoding. Your project looks like it could work, but it is not idiomatic, why not name those functions Marshal and Unmarshal and meet the same interface?Kicksorter
Thank for the feedback. I could make mine more idiomatic. Mine currently only encodes though too.Bergess

© 2022 - 2024 — McMap. All rights reserved.