¿Hay un paquete para entrar y salir de x-www-form-urlencoding en golang
Me gustaría entrar y salir de x-www-form-urlencoding similar a cómo se puede hacer con json o xml. ¿Existe un paquete para hacer esto, o hay algún documento sobre cómo implementar uno yo mismo si no existe?
4 answers
Gorilla/schema es popular y bien mantenido:
Por ejemplo
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 es también una alternativa.
Actualización 23 de mayo 2015:
- gorilla/schema sigue siendo mi elección como uno de los paquetes de map-to-struct más soportados, con los valores de formulario POST siendo un caso de uso común.
- goji/param también es bastante sólido y tiene muchas de las mismas características.
- mholt / binding está un poco más lleno de funciones a expensas (IMO) de una API un poco más compleja.
He estado usando gorilla/schema durante un par de años y no he tenido ningún problema importante con él. Lo uso junto con vala para validar entradas (no nil, demasiado corto, demasiado largo, etc.) antes de que lleguen a la base de datos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-16 02:07:39
Acabo de encontrar https://github.com/ajg/form que es exactamente lo que estaba buscando. También hay https://github.com/gorilla/schema para decodificar estrictamente y https://github.com/google/go-querystring para codificación estricta.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-22 18:12:14
Https://github.com/google/go-querystring es bueno, pero no soporta mapas (y porciones de mapas).
Empecé https://github.com/drewlesueur/querystring para soporte de mapas. (Todavía no admite estructuras, pero las solicitudes de extracción son bienvenidas).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-25 19:21:27
El paquete "github.com/pasztorpisti/qs"
también puede combinar estructuras/unmarshal a/desde cadenas de consulta y formas POST
-ed.
Ejemplo:
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>
}
Posibles puntos de venta de este paquete:
- Los nombres de los campos de estructura aparecen automáticamente como
snake_case
en la cadena de consulta. No es necesario agregarqs:"field_name"
a la etiqueta de campo struct para esto. Este comportamiento se puede cambiar. - Arquitectura modular que permite reemplazar marshalers y unmarshalers incluso para tipos incorporados (como
bool
,[]byte
) y agregue soporte para nuevos tipos sin modificar el tipo en sí (por ejemplo: agregue marshaling y / o unmarshaling paratime.Time
). Aquí es un ejemplo. - Puede agregar la opción
req
a la etiqueta de campo de estructura para hacer que el campo sea obligatorio mientras se desmarca. Tenga en cuenta que esto es más bien la validación que unmarshaling y las bibliotecas de golang suelen ir para la separación entre los dos, pero me pareció esta opción muy útil porque se necesita a menudo, es simple y se lee bien. Para aquellos que desean evitarreq
y hacer esta validación por separado después de desmarcar: hay una opción de etiquetanil
que es más o menos la misma que la predeterminadaopt
(que significa "opcional"), excepto que no inicializa los punteros nil cuando los campos dados no están en la cadena de consulta sin marcar. De esta manera, el código del validador puede detectar los campos que faltan al buscar punteros nil después de desmarcar. -
El paquete
qs
puede decir si un tipo complejo (por ejemplo: su estructura) es marshalable antes de organizar una instancia de ese tipo. La mayoría de los paquetes marshaler no pueden hacer esto incluso después de ordenar una instancia del tipo dado! La mayoría de los marshalers examinan tipos complejos recorriendo el objeto que se está marshaleando y comprobando los tipos solo para los subobjetos visitados. Esto significa que si el objeto complejo contiene un contenedor (puntero, mapa o segmento) que está vacío, el tipo de elemento del contenedor ni siquiera se examina. En contractqs
recorre la estructura de tipo del objeto complejo (en lugar del objeto en sí) mientras se crea el marshaler para el tipo para que falle donde tiene que fallar. Considere el siguiente código en el que el paquete estándar"encoding/json"
gestiona con éxito un objeto cuyo tipo contiene un tipo no marshalable: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() }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-21 22:56:57