英文:
Decoding JSON from POST request fails in Go
问题
我用以下的JSON数据向我的Go应用程序发送了一个POST请求:
var test = {text: "Lorem ipsum dolor sit amet"};
$.ajax({
url: "/api/test/add",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(test),
success: function(data) {
// ...
},
error: function(xhr, status, err) {
// ...
}
});
在我的Go应用程序中,我有以下的代码(使用vestigo):
type Test struct {
id int
text string
}
func apiAddTestHandler(w http.ResponseWriter, r *http.Request) {
r_body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
// 如果我尝试将r_body转换为字符串(string(r_body)),我会得到{"text": "Lorem ipsum dolor sit amet"},看起来一切都正常。
var test Test
err = json.Unmarshal(r_body, &test)
if err != nil {
panic(err)
}
// 在下面处理test结构体时,我得到{id:0 text:},如果我尝试使用或打印test的值(fmt.Printf("%+v\n", test))。
}
func main() {
router := vestigo.NewRouter()
router.Post("/api/test/add", apiAddTestHandler)
err := http.ListenAndServe(":3000", router)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
问题是,在apiAddTestHandler()函数中,我无法将解码后的JSON数据填充到test结构体中。在注释中有更多的信息。我还尝试了下面的代码片段,但没有成功:
decoder := json.NewDecoder(r.Body)
var test Test
err := decoder.Decode(&test)
if err != nil {
panic(err)
}
问题出在哪里?
英文:
I send a POST request to my Go application with JSON data like below:
var test = {text: "Lorem ipsum dolor sit amet"};
$.ajax({
url: "/api/test/add",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(test),
success: function(data) {
// ...
},
error: function(xhr, status, err) {
// ...
}
});
In my Go application I have the following code (using vestigo):
type Test struct {
id int
text string
}
func apiAddTestHandler(w http.ResponseWriter, r *http.Request) {
r_body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
// Here looks like everything is ok because I get
// {"text": "Lorem ipsum dolor sit amet"} if I try
// to convert r_body to string (string(r_body)).
var test Test
err = json.Unmarshal(r_body, &test)
if err != nil {
panic(err)
}
// Process test struct below, but here I get
// {id:0 text:} if I try to use or print the value
// of test (fmt.Printf("%+v\n", test)).
}
func main() {
router := vestigo.NewRouter()
router.Post("/api/test/add", apiAddTestHandler)
err := http.ListenAndServe(":3000", router)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
The problem is, that in apiAddTestHandler() I cannot "populate" the test struct with the decoded JSON data. A little bit more info in the comments. I also tried the below snippet with no luck:
decoder := json.NewDecoder(r.Body)
var test Test
err := decoder.Decode(&test)
if err != nil {
panic(err)
}
What is the problem?
答案1
得分: 3
从Unmarshal
文档中(强调是我的):
> 为了将JSON解组为结构体,Unmarshal将传入的对象键与Marshal使用的键进行匹配(可以是结构字段名称或其标签),优先选择精确匹配,但也接受不区分大小写的匹配。Unmarshal只会设置结构体的导出字段。
您需要更改结构体中的字段定义:
type Test struct {
ID int
Text string
}
请注意,根据Golang命名约定,我使用了ID
而不是Id
。
英文:
From the Unmarshal
documentation (emphasis is mine):
> To unmarshal JSON into a struct, Unmarshal matches incoming object keys to the keys used by Marshal (either the struct field name or its tag), preferring an exact match but also accepting a case-insensitive match. Unmarshal will only set exported fields of the struct.
You need to change the field definition in your struct:
type Test struct {
ID int
Text string
}
Note I used ID
instead of Id
per Golang naming conventions.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论