英文:
Parse req.body in POST request
问题
我正在使用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
})
我想将email
和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
时,我得到一个空格。解析它的正确方法是什么?
英文:
I am using fetch
API to send two values to my POST
request handler...
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
})
I want to save both email
and password
as strings on the server side. Here is my attempt...
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)
}
The problem is I do not know how exactly the format of the structure being sent to the POST
. I am attempting to save req.Body
as a string but this yields nothing.
When I print fmt.Println
I get a blank space. What is the proper way of parsing it?
答案1
得分: 5
尝试使用以下代码:
type credentials struct {
Email string `json:"email"`
Password string `json:"password"`
}
您将收到一个包含两个值的 JSON。接收结构体应该具有与您的请求匹配的结构。否则,没有占位符可以将 JSON 解码为,就像您的情况一样 - 邮件和密码没有匹配的结构字段。顺便说一下,如果您在 JSON 中发送 "Test",这将起作用,因为您的结构中有一个 Test 字段!
关于字段名称。如果 JSON 中的字段不以大写字母开头,甚至具有不同的名称,那么您应该使用所谓的标签(tags)。
有关标签的更多信息:https://golang.org/pkg/encoding/json/#Marshal
在我的示例中,我使用它们将结构字段名称与您的 JSON 字段匹配,即使将 JSON 中的 "email" 匹配到 "credentials" 结构体的 "Email" 字段。
英文:
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.
答案2
得分: 2
req.Body
是一个 io.Reader
,你可以使用 ioutil.ReadAll
来读取它:
data, err := ioutil.ReadAll(req.Body)
asString := string(data) // 你可以通过类型转换将其转换为字符串
但我不确定你是否想要将 req.Body
保存为字符串。
要将响应解析为数据结构,你可以将其解组为类型为 *interface{}
的变量:
var creds interface{}
decoder.Decode(&creds)
然后检查该值:
fmt.Printf("%#v\n", creds)
或者你可以使用 pp.Println(creds)
,我觉得这样更容易阅读。
creds
变量将表示在请求体中找到的 JSON 对象,对于你的示例输入,它将是一个 map[string]interface{}
,其中包含两个条目,可能都是字符串。类似于:
map[string]interface{}{
"email": email_value,
"password": password_value,
}
你可以使用以下代码检查这些值:
email, ok := creds["email"].(string)
if ok {
// email 将包含该值,因为 creds["email"] 通过了类型检查
fmt.Printf("submitted email is %#v\n", email)
} else {
// "email" 属性是一个字符串(可能缺失,也可能是其他类型)
}
json.Unmarshal
的文档 在关于解组为接口值的讨论中解释了如何解析任意 JSON 字符串而不事先知道其结构的语义。
英文:
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\n", 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\n", 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论