求助:解析POST请求中的req.body

我正在使用fetch API 将两个值发送到我的 POST 请求处理程序:

fetch('http://localhost:8080/validation', {
        method:'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            email:this.state.email,
            password:this.state.password
        })

我想在服务器端保存电子邮件和密码为字符串,以下是我的尝试:

type credentials struct {
    Test string
}

func Validate(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {

    decoder := json.NewDecoder(req.Body)

    var creds credentials

    err := decoder.Decode(&creds)

    if err != nil {
        panic(err)
    }

    fmt.Println(creds.Test)
}

问题是我不知道发送到 POST 结构的确切格式。我正在尝试将 req.Body 保存为字符串,但是没有得到任何结果。

当输入 fmt.Println 只得到一个空格,解析它的正确方法是什么?

Try with

type credentials struct {
    Email string `json:"email"`
    Password string `json:"password"`
}

You are receiving a JSON with two values. Receiving struct should have a structure matching your request. Otherwise, there are no placeholders to decode the JSON into, as in your case - email and password do not have matching struct fields. Btw. if you send "Test" in your JSON, this would work, as you have a Test field in your struct!

Regarding field names. If fields in JSON do not start with a capital letter or even have different names, then you should use so called tags. More on tags: https://golang.org/pkg/encoding/json/#Marshal

In my example I used them to match struct field names to your json fields, i.e. to make email from json match Email field of the credentials struct.

req.Body is an io.Reader, and you can get use ioutil.ReadAll to drain it:

data, err := ioutil.ReadAll(req.Body)
asString := string(data) // you can convert to a string with a typecast

But I'm not sure if that's what you meant by trying to save req.Body as a string.

To parse the response into a data structure, you can unmarshal it into a variable of type *interface{}:

var creds interface{}
decoder.Decode(&creds)

And then examine the value:

fmt.Printf("%#v
", creds)

Or perhaps using pp.Println(creds) which I find easier to read.

The creds variable will represent the JSON object found in the body, for your example input this will be a map[string]interface{} with two entries, presumably both of them strings. Something like:

map[string]interface{}{
    "email": email_value,
    "password": password_value,
}

and you check the values with:

email, ok := creds["email"].(string)
if ok {
    // email will contain the value because creds["email"] passed the type check
    fmt.Printf("submitted email is %#v
", email)
} else {
    // "email" property was a string (may be missing, may be something else)
}

The documentation of json.Unmarshal explains the semantics of how arbitrary JSON strings can be parsed without knowing their structure in advance in the discussion about unmarshalling to interface values.