Manejo de la solicitud JSON Post en Go
Así que tengo lo siguiente, que parece increíblemente hackeado, y he estado pensando que Go tiene bibliotecas mejor diseñadas que esto, pero no puedo encontrar un ejemplo de Go manejando una solicitud POST de datos JSON. Todos son mensajes de formulario.
Aquí hay una solicitud de ejemplo: curl -X POST -d "{\"test\": \"that\"}" http://localhost:8082/test
Y aquí está el código, con los registros incrustados:
package main
import (
"encoding/json"
"log"
"net/http"
)
type test_struct struct {
Test string
}
func test(rw http.ResponseWriter, req *http.Request) {
req.ParseForm()
log.Println(req.Form)
//LOG: map[{"test": "that"}:[]]
var t test_struct
for key, _ := range req.Form {
log.Println(key)
//LOG: {"test": "that"}
err := json.Unmarshal([]byte(key), &t)
if err != nil {
log.Println(err.Error())
}
}
log.Println(t.Test)
//LOG: that
}
func main() {
http.HandleFunc("/test", test)
log.Fatal(http.ListenAndServe(":8082", nil))
}
Tiene que haber una mejor manera, ¿verdad? Estoy perplejo al encontrar cuál podría ser la mejor práctica.
(Go también se conoce como Golang a los motores de búsqueda, y se menciona aquí para que otros puedan encontrarlo.)
4 answers
Utilice json.Decoder
en lugar de json.Unmarshal
.
func test(rw http.ResponseWriter, req *http.Request) {
decoder := json.NewDecoder(req.Body)
var t test_struct
err := decoder.Decode(&t)
if err != nil {
panic(err)
}
log.Println(t.Test)
}
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
2018-06-20 17:35:10
Necesitas leer de req.Body
. El método ParseForm
está leyendo desde el req.Body
y luego analizándolo en formato estándar codificado HTTP. Lo que quieres es leer el cuerpo y analizarlo en formato JSON.
Aquí está tu código actualizado.
package main
import (
"encoding/json"
"log"
"net/http"
"io/ioutil"
)
type test_struct struct {
Test string
}
func test(rw http.ResponseWriter, req *http.Request) {
body, err := ioutil.ReadAll(req.Body)
if err != nil {
panic(err)
}
log.Println(string(body))
var t test_struct
err = json.Unmarshal(body, &t)
if err != nil {
panic(err)
}
log.Println(t.Test)
}
func main() {
http.HandleFunc("/test", test)
log.Fatal(http.ListenAndServe(":8082", nil))
}
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-02-06 08:49:24
Me estaba volviendo loco con este problema exacto. Mi JSON Marshaller y Unmarshaller no estaban poblando mi estructura Go. Entonces encontré la solución en https://eager.io/blog/go-and-json :
"Al igual que con todas las estructuras en Go, es importante recordar que solo los campos con una primera letra mayúscula son visibles para programas externos como el JSON Marshaller."
Después de eso, mi Marshaller y mi Unmshaller funcionaron perfectamente!
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
2016-03-15 00:01:24
Encontré el siguiente ejemplo de los documentos realmente útil (fuente aquí).
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"strings"
)
func main() {
const jsonStream = `
{"Name": "Ed", "Text": "Knock knock."}
{"Name": "Sam", "Text": "Who's there?"}
{"Name": "Ed", "Text": "Go fmt."}
{"Name": "Sam", "Text": "Go fmt who?"}
{"Name": "Ed", "Text": "Go fmt yourself!"}
`
type Message struct {
Name, Text string
}
dec := json.NewDecoder(strings.NewReader(jsonStream))
for {
var m Message
if err := dec.Decode(&m); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
fmt.Printf("%s: %s\n", m.Name, m.Text)
}
}
La clave aquí es que el OP estaba buscando decodificar
type test_struct struct {
Test string
}
} en cuyo caso eliminaríamos el const jsonStream
, y reemplazaríamos la estructura Message
con el test_struct
:
func test(rw http.ResponseWriter, req *http.Request) {
dec := json.NewDecoder(req.Body)
for {
var t test_struct
if err := dec.Decode(&t); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
log.Printf("%s\n", t.Test)
}
}
Actualización : También añadiría que este post proporciona algunos datos excelentes sobre cómo responder con JSON también. El autor explica struct tags
, que yo no conocía.
Desde JSON normalmente no se parece a {"Test": "test", "SomeKey": "SomeVal"}
, sino a {"test": "test", "somekey": "some value"}
, puedes reestructurar tu estructura de esta manera:
type test_struct struct {
Test string `json:"test"`
SomeKey string `json:"some-key"`
}
...y ahora su manejador analizará JSON usando " some-key "en lugar de" someKey " (que usará internamente).
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
2016-09-23 14:26:25