Обработка запроса JSON Post в Go



Итак, у меня есть следующее, что кажется невероятно хакерским, и я думал про себя, что Go имеет более совершенные библиотеки, чем это, но я не могу найти пример обработки запроса POST данных JSON. Все они формируют посты.



вот пример запрос: curl -X POST -d "{"test": "that"}" http://localhost:8082/test



и вот код, с логами встроенных:



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


там должен быть лучший способ? Я просто в тупике в поиске того, что может быть лучшей практикой.



(Go также известен как Golang для поисковых систем и упоминается здесь, чтобы другие могли его найти.)

782   4  

4 ответов:

пожалуйста, используйте json.Decoder вместо 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)
}

вам нужно прочитать от req.Body. Элемент ParseForm метод считывает из req.Body и затем разбор его в стандартном формате http-кодирования. Вы хотите прочитать тело и проанализировать его в формате JSON.

вот ваш код обновлен.

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

я сводил себя с ума именно с этой проблемой. Мой JSON Marshaller и Unmarshaller не заполняли мою структуру Go. Затем я нашел решение в https://eager.io/blog/go-and-json:

" Как и во всех структурах в Go, важно помнить, что только поля с заглавной первой буквой видны внешним программам, таким как JSON Marshaller."

после этого, мой marshaller и вызывается работал отлично!

я нашел следующий пример из документов действительно полезным (source здесь).

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

ключевым моментом здесь является то, что ОП искал, чтобы раскодировать

type test_struct struct {
    Test string
}

...в этом случае мы бы отбросить const jsonStream и заменить Message структура с 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)
    }
}

обновление: я бы также добавил, что этот пост предоставляет некоторые большие данные об ответе с JSON, а также. Автор объясняет struct tags, о котором я не знал.

так как JSON обычно не выглядит как {"Test": "test", "SomeKey": "SomeVal"}, а {"test": "test", "somekey": "some value"}, вы можете реструктурировать свою структуру следующим образом:

type test_struct struct {
    Test string `json:"test"`
    SomeKey string `json:"some-key"`
}

...и теперь ваш обработчик будет анализировать JSON, используя "some-key", а не" SomeKey " (который вы будете использовать внутри).

Comments

    Ничего не найдено.