Então, eu tenho o seguinte, que parece incrivelmente hacky, e eu tenho pensado comigo mesmo que o Go tem bibliotecas projetadas melhor do que isso, mas não consigo encontrar um exemplo de Go manipulando uma solicitação POST de dados JSON. Todos são POSTs de formulário.
Aqui está um exemplo de solicitação: curl -X POST -d "{\"test\": \"that\"}" http://localhost:8082/test
E aqui está o código, com os logs incorporados:
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))
}
Tem que haver uma maneira melhor, certo? Estou perplexo ao descobrir qual poderia ser a melhor prática.
(Go também é conhecido como Golang para os mecanismos de pesquisa e mencionado aqui para que outros possam encontrá-lo.)
curl -X POST -H 'Content-Type: application/json' -d "{\"test\": \"that\"}"
, entãoreq.Form["test"]
deve retornar"that"
Respostas:
Por favor, use em
json.Decoder
vez dejson.Unmarshal
.fonte
defer req.Body.Close()
Dos documentos: "O servidor fechará o corpo da solicitação. O manipulador ServeHTTP não precisa". Também para responder @thisisnotabus, nos documentos: "Para solicitações do servidor, o Corpo da Solicitação é sempre nulo, mas retornará o EOF imediatamente quando nenhum corpo estiver presente" golang.org/pkg/net/http/#Requestjson.Decoder
. Ele é destinado a fluxos de objetos JSON, não a um único objeto. Não é mais eficiente para um único objeto JSON, pois ele lê o objeto inteiro na memória. Tem uma desvantagem de que, se o lixo for incluído após o objeto, ele não reclamará. Dependendo de alguns fatores,json.Decoder
pode não ser totalmente lido o corpo e a conexão não estará qualificada para reutilização.Você precisa ler
req.Body
. OParseForm
método está lendoreq.Body
e analisando-o no formato codificado em HTTP padrão. O que você deseja é ler o corpo e analisá-lo no formato JSON.Aqui está seu código atualizado.
fonte
req.ParseForm()
, o que eu estava fazendo nas tentativas anteriores de tentar resolver esse problema, antes de tentar ler oreq.Body
unexpected end of JSON input
Unmarshal
json.NewDecoder(req.Body)
também estão corretas.Eu estava enlouquecendo com esse problema exato. Meu JSON Marshaller e Unmarshaller não estavam preenchendo minha estrutura Go. Encontrei a solução em https://eager.io/blog/go-and-json :
Depois disso, meu Marshaller e Unmarshaller funcionaram perfeitamente!
fonte
Há duas razões pelas quais
json.Decoder
deve ser preferível ao invésjson.Unmarshal
- que não são abordadas na resposta mais popular de 2013:go 1.10
introduziu um novo método json.Decoder.DisallowUnknownFields (), que aborda a preocupação de detectar entradas JSON indesejadasreq.Body
já é umio.Reader
. Lendo todo o seu conteúdo e, em seguida, realizandojson.Unmarshal
desperdícios de recursos, se o fluxo for, digamos, um bloco de 10 MB de JSON inválido. A análise do corpo da solicitação, comjson.Decoder
, conforme ele é transmitido , acionaria um erro de análise antecipada se JSON inválido fosse encontrado. O processamento de fluxos de E / S em tempo real é o caminho preferido .Abordando alguns dos comentários do usuário sobre a detecção de entrada incorreta do usuário:
Para impor campos obrigatórios e outras verificações de saneamento, tente:
Parque infantil
Saída típica:
fonte
Achei o exemplo a seguir dos documentos realmente útil (fonte aqui ).
A chave aqui é que o OP estava tentando decodificar
... nesse caso, soltaríamos o
const jsonStream
e substituiríamos aMessage
struct pelotest_struct
:Atualização : Eu também acrescentaria que este post também fornece ótimos dados sobre como responder com JSON. O autor explica
struct tags
, do qual eu não estava ciente.Desde JSON normalmente não parecer
{"Test": "test", "SomeKey": "SomeVal"}
, mas sim{"test": "test", "somekey": "some value"}
, você pode reestruturar a sua estrutura como esta:... e agora seu manipulador analisará JSON usando "some-key" em vez de "SomeKey" (que você usará internamente).
fonte
fonte