go - online - urlencode live
¿Hay algún paquete para incluir y salir de x-www-form-urlencoding en golang? (4)
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 codificar estrictamente.
Me gustaría ingresar dentro y fuera de x-www-form-urlencoding de manera similar a como puedes hacerlo con json o xml. ¿Hay un paquete existente para hacer esto, o hay documentos sobre cómo implementar uno mismo si no existe ninguno?
gorilla/schema es popular y bien mantenido:
p.ej
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 del 23 de mayo de 2015:
- gorilla / schema sigue siendo mi elección como uno de los paquetes map-to-struct más compatibles, con valores de formulario POST como un caso de uso común.
- goji/param también es bastante sólido y tiene muchas de las mismas características.
- mholt/binding es una característica un poco más empaquetada a expensas de una API un poco más compleja.
He estado usando gorila / esquema por un par de años y no he tenido ningún problema importante con él. Lo uso junto con vala para validar entradas (no nulas, demasiado cortas, demasiado largas, etc.) antes de que lleguen a la base de datos.
https://github.com/google/go-querystring es bueno, pero no admite mapas (y partes de mapas).
Comencé https://github.com/drewlesueur/querystring para el soporte de mapas. (Todavía no admite estructuras, pero las solicitudes de extracción son bienvenidas).
El paquete "github.com/pasztorpisti/qs"
también puede ordenar las estructuras / unmarshal a / desde cadenas de consulta y formularios de POST
.
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 campo de Struct aparecen automáticamente como
snake_case
en la cadena de consulta. No tiene que agregarqs:"field_name"
a la etiqueta del campo de estructura para esto. Este comportamiento puede ser cambiado. - Arquitectura modular que le permite a uno reemplazar a los calificadores y desarmadores incluso para los tipos incorporados (como
bool
,[]byte
) y agregar soporte para los nuevos tipos sin modificar el tipo en sí (por ejemplo: agregar cálculo detime.Time
y / o desalojar paratime.Time
). Here hay un ejemplo. - Puede agregar la opción
req
a la etiqueta del campo de estructura para hacer que el campo sea requerido mientras se desmarca. Tenga en cuenta que esto es más una validación que unarsarsing y que las bibliotecas de golang usualmente se separan entre las dos, pero esta opción me parece muy útil porque es necesaria a menudo, es simple y se lee bien. Para aquellos que desean evitar lareq
y hacer esta validación por separado después de unmarshaling: hay una opción de etiquetanil
que es prácticamente la misma que laopt
predeterminada (que significa "opcional"), excepto que no inicializa los punteros nulos cuando los campos dados no se encuentran en la cadena de consulta no zarshaled. De esta manera, el código del validador puede detectar los campos faltantes buscando nil punteros después de desmarcar. El paquete
qs
puede indicar si un tipo complejo (por ejemplo: su estructura) es compaginable antes de calcular realmente una instancia de ese tipo. ¡La mayoría de los paquetes de marshaler no pueden hacer esto incluso después de calcular una instancia del tipo dado! La mayoría de los encuestadores examinan los tipos complejos recorriendo el objeto que se está calculando y verificando los tipos solo para los objetos secundarios visitados. Esto significa que si el objeto complejo contiene un contenedor (puntero, mapa o sector) que está vacío, el tipo de elemento del contenedor ni siquiera se examina. En el contratoqs
recorre la estructura de tipos del objeto complejo (en lugar del objeto en sí) mientras se crea el contador de referencias para el tipo, de modo que falla donde tiene que fallar. Considere el siguiente código en el que el paquete estándar"encoding/json"
correctamente un objeto cuyo tipo contiene un tipo no comercializable: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() }