You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用htmx表单向Gin服务器传值:无法正确读取请求体

问题:使用htmx json-enc扩展向Gin服务器传递表单值的正确方式

我用带json-enc扩展的htmx表单,想把第一个输入框的todo值发送到Gin服务器,但后端获取请求体时得到的是URL编码的字节数组,不是JSON格式。

前端代码:

<form hx-post="/addToDo" hx-ext="json-enc" hx-trigger="submit" hx-target="#todos" hx-swap="outerHTML">
    <input type="text" placeholder="todo" name="todo" />
    <input type="submit" />
</form>

<ol id="todos"></ol>

Gin后端代码:

r.POST("/addToDo", func(c *gin.Context) {
    fmt.Println(c.Request.Body)
    // 输出: &{0xc0000b2000 <nil> <nil> false true {0 0} false false false 0xeaee20}

    jsonData, err := ioutil.ReadAll(c.Request.Body)

    if err != nil {
        fmt.Println("something went wrong here boys")
        return
    }

    fmt.Println(jsonData)
    // 输出: [116 111 100 111 61 104 101 108 108 111]
})

我不想用URL参数传递,确定可以通过请求体实现,想知道怎么正确获取请求体或todo输入值?


解决方案

问题根源

你看到的字节数组是todo=hello的URL编码形式,说明json-enc扩展没有生效,表单还是以默认的application/x-www-form-urlencoded格式发送请求,而非JSON格式。

步骤1:确保正确引入json-enc扩展

必须在htmx核心库之后加载json-enc扩展脚本,否则扩展无法被htmx识别:

<script src="https://unpkg.com/htmx.org@1.9.10"></script>
<script src="https://unpkg.com/htmx.org/dist/ext/json-enc.js"></script>

步骤2:后端解析JSON格式请求

当json-enc生效后,请求体将是{"todo": "你的输入值"}这种JSON结构,用Gin的ShouldBindJSON方法可以轻松解析:

首先定义对应结构体:

type TodoRequest struct {
    Todo string `json:"todo"` // 字段名要和表单name一致,json标签对应JSON键名
}

然后修改处理函数:

import "net/http"

// ...

r.POST("/addToDo", func(c *gin.Context) {
    var req TodoRequest
    // 解析JSON请求体到结构体
    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "请求格式错误"})
        return
    }

    // 成功获取todo值
    fmt.Println("收到的todo内容:", req.Todo)

    // 这里可以添加业务逻辑,比如保存到数据库
    // 然后返回更新后的todos列表(对应hx-target的#todos)
    c.HTML(http.StatusOK, "todos_partial.html", gin.H{
        "todos": []string{req.Todo}, // 示例数据,实际替换为真实列表
    })
})

备选方案:直接解析表单格式(无需json-enc)

如果暂时不想用JSON格式,也可以跳过json-enc,直接用Gin的PostForm方法获取表单值,这种方式更简单:

r.POST("/addToDo", func(c *gin.Context) {
    // 直接通过表单name获取值
    todo := c.PostForm("todo")
    if todo == "" {
        c.JSON(http.StatusBadRequest, gin.H{"error": "todo不能为空"})
        return
    }

    fmt.Println("收到的todo内容:", todo)
    // 处理逻辑...
})

内容的提问来源于stack exchange,提问作者AyeAreEm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 20:13:27