print handling golang deserialize json go

handling - json to interface golang



Manejo de solicitud de publicaciĆ³n de JSON en Go (4)

Entonces tengo lo siguiente, que parece increíblemente intrépido, y me he estado pensando a mí mismo 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 formularios POSTs.

Aquí hay un ejemplo de solicitud: 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? Simplemente estoy perplejo al encontrar lo que podría ser la mejor práctica.

(Go también se conoce como Golang para los motores de búsqueda, y se menciona aquí para que otros puedan encontrarlo).


Encontré el siguiente ejemplo de la documentación realmente útil (fuente here ).

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, descartaríamos la const jsonStream y reemplazaríamos la estructura de Message con 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 agregaría que esta publicación proporciona información excelente sobre cómo responder con JSON también. El autor explica las struct tags , de las que no tenía conocimiento.

Como JSON normalmente no se ve como {"Test": "test", "SomeKey": "SomeVal"} , sino más bien {"test": "test", "somekey": "some value"} , puede reestructurar su estructura así:

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).


Me estaba volviendo loco con este problema exacto. Mi JSON Marshaller y Unmarshaller no estaban poblando mi estructura Go. Luego 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 Unmarshaller funcionaron perfectamente.


Necesitas leer desde req.Body . El método ParseForm está leyendo desde req.Body y luego req.Body en formato codificado HTTP estándar. Lo que quieres es leer el cuerpo y analizarlo en formato JSON.

Aquí está su 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)) }


Utilice json.Decoder 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) }