go - Echo 框架 Bind() html FormData
问题描述
我有一个表单 html,如:
<input name="email"type="email" />
<input name="password"type="password" />
<input name="tags[name][]"type="text" />
<input name="tags[count][]"type="number" />
<input name="tags[name][]"type="text" />
<input name="tags[count][]"type="number" />
<input name="tags[name][]"type="text" />
<input name="tags[count][]"type="number" />
<input name="freeword[]"type="text" />
<input name="freeword[]"type="text" />
我想Bind()
用我struct
喜欢的形式填写:
type UserFrom struct {
Email string `json:"email" form:"email" query:"email"`
Password string `json:"password" form:"password" query:"password"`
Tags []Tag
Free []string `json:"freeword[]" form:"freeword[]" query:"freeword[]"`
}
type Tag struct {
Name string `json:"tags[name][]" form:"tags[name][]" query:"tags[name][]"`
Count string `json:"tags[count][]" form:"tags[count][]" query:"tags[count][]"`
}
Bind()
但是,如果我在我拥有之后打印结果POST
:
u := new(UserFrom)
if err = c.Bind(u); err != nil {
return
}
log.Println(u)
这个不好的输出:
&{email@mail.tld pwdpwdpwd [] [word1 word2]}
Tags []Tag
结构中的行UserFrom
不起作用
如果您尝试更改Tags []Tag
为Tags Tag
我有一个很好的最后一个条目
&{email@mail.tld pwdpwdpwd {tag3 3} [word1 word2]}
我想要这个输出:
&{email@mail.tld pwdpwdpwd [{tag1 1} {tag2 2} {tag3 3}] [word1 word2]}
你知道这个问题吗?
解决方案
有两个问题:
- 您没有正确指定表单输入名称,您拥有它们的方式永远无法映射到您想要的任何语言。在支持您想要的语言中,它将标签映射到两个字段(名称和计数)的结构,每个字段都由一个数组组成。不是名称和计数的结构数组。名称应该是这样
tags[][name]
才能实现您想要的,例如,请参见此处:HTML Form: POST an array of objects - 即使您按照上述正确指定了名称,它也无法在 Echo 中工作,因为它依赖于
http.Request.Form
解析值,这实际上url.Values
只是一个map[string][]string
. 如您所见,这不可能捕获您想要的结构。这是一张相关的票:https ://github.com/golang/go/issues/29703
现在,仅仅因为 Echo 不支持开箱即用,并不意味着您不能这样做。您可以使用具有所需功能的 3rd 方库进行绑定,例如https://github.com/monoculum/formam
以下代码:
package main
import (
"fmt"
"net/url"
"github.com/monoculum/formam"
)
type User struct {
Email,
Password string
Tags []struct {
Tag string
Count int
}
}
func main() {
formData := "Email=joe@example.com&Password=secret&Tags[0].Tag=red&" +
"Tags[0].Count=1&Tags[1].Tag=blue"
q, _ := url.ParseQuery(formData)
u := new(User)
dec := formam.NewDecoder(nil)
if err := dec.Decode(q, u); err != nil {
fmt.Println(err)
return
}
fmt.Println(u)
}
结果是你需要的:
&{joe@example.com secret [{red 1} {blue 0}]}
希望这可以帮助!
推荐阅读
- c# - XUnit + Alba 创建 2 个 DbContexts 而不是 1 个
- c++ - Ubuntu 20.04:valgrind:“memcheck-amd64-linux”意外关闭
- python - pyenv 使用系统 python 而不是虚拟环境
- flutter - Flutter:小部件的某些部分不显示
- android - Android Kotlin recyclerview 里面的 recyclerview onScrollListener 只调用了一次
- math - 来自 3 个向量的 3D 立方体旋转
- java - 如何在用户位置附近显示兽医
- c# - C# RSA Encrpytion -> Laravel phpseclib 解密()
- kubernetes - 使用 Terraform 和 GitlabCI 处理多个应用 Kubernetes 部署
- node.js - 无法使用 Wolfram Alpha API 部署到 heroku