Golang请求体(Request Body)解析方法与技巧

Golang请求体(Request Body)解析方法与技巧 我正在尝试从POST请求中解析请求体参数(JSON对象)。

我尝试了以下方法:

var user models.User

decoder := json.NewDecoder(request.Body)
decoder.Decode(&user)

fmt.Println(user)

但是它返回:

{0   }

我哪里做错了?

非常感谢任何帮助。

9 回复

检查Decode返回的错误。

更多关于Golang请求体(Request Body)解析方法与技巧的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


@calmh,我试过了,错误是 nil。

请记得通过点击复选框将问题标记为已回答。

感谢 @Christophe_Meessen,这解决了我的问题。图片

以下是我的 user_models.go 文件:

package models

// User : 用户模型
type User struct {
    id        int
    firstName string
    lastName  string
    password  string
}

你能展示一下 models.User 的定义吗?

看起来它只包含一个字段。你期望的用户值是什么?

可能是 models.User 只有未导出的字段(名称不是以大写字母开头),或者结构体定义缺少 json 标签。

请注意,如果你无法修改 models.User,因为它来自一个你无法或不应修改的包,那么你应该使用一个具有上述定义的中间结构,将 JSON 数据解码到其中,然后将每个字段值复制到 models.User 结构中。

这种中间结构是一种常用的模式。

因此,它存在两个问题,使其不适合用作 JSON 输出。

  1. JSON 解码器只考虑导出的结构体字段名。当字段名的首字母为大写时,该字段名才是导出的。
  2. 由于 JSON 编码数据中的字段名通常是小写的,我们必须指定 JSON 字段名与结构体字段名之间的映射。这可以通过使用标签来实现。标签是包含在反引号中的字符串,放置在字段定义的右侧。

以下是您应该如何定义 models.User 结构体。

type User struct {
    ID int `json:id`
    FirstName string `json:firstName`
    LastName string `json:lastName`
    Password string `json:password`
}

json: 后面的值是 JSON 编码数据中的字段名。如果您能提供一个 JSON 编码数据的示例,我就能确定那里应该放什么值。我假设这些是 JSON 编码数据中的字段名。

看起来你在解析JSON请求体时遇到了问题。{0 } 表示结构体字段没有被正确赋值。这通常是因为JSON字段名与Go结构体字段名不匹配导致的。

让我提供一个完整的示例:

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

// 确保结构体字段是导出的(首字母大写)
type User struct {
    ID       int    `json:"id"`      // JSON标签指定字段映射
    Name     string `json:"name"`
    Email    string `json:"email"`
}

func handler(w http.ResponseWriter, r *http.Request) {
    var user User
    
    // 方法1: 使用json.NewDecoder
    decoder := json.NewDecoder(r.Body)
    err := decoder.Decode(&user)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    
    // 方法2: 使用json.Unmarshal
    // body, _ := ioutil.ReadAll(r.Body)
    // json.Unmarshal(body, &user)
    
    fmt.Printf("解析结果: %+v\n", user)
    fmt.Fprintf(w, "用户: %+v", user)
}

func main() {
    http.HandleFunc("/user", handler)
    http.ListenAndServe(":8080", nil)
}

关键点:

  1. 结构体字段必须导出(首字母大写)
  2. 使用JSON标签指定字段映射关系
  3. 检查错误decoder.Decode() 返回错误需要处理
  4. 使用%+v格式化:可以显示结构体字段名

测试用的JSON请求体应该像这样:

{
    "id": 1,
    "name": "张三",
    "email": "zhangsan@example.com"
}

如果JSON字段名是下划线风格(如user_name),而Go结构体是驼峰风格(如UserName),JSON标签可以解决这个问题:

type User struct {
    UserName string `json:"user_name"`
}

另外,确保请求的Content-Type是application/json,并且请求体是有效的JSON格式。

回到顶部