Versions Compared
Key
- This line was added.
- This line was removed.
- Formatting was changed.
对象转换
对象转换在请求处理中非常常见。我们推荐将输入和输出定义为struct
结构体对象,以便于结构化的参数输入输出维护。GoFrame
框架支持非常便捷的对象转换,支持将客户端提交的参数如Query
参数、表单参数、内容参数、JSON/XML
等参数非常便捷地转换为指定的struct
结构体,并且支持提交参数与struct
属性的映射关系维护。
对象转换方法使用Request
对象的Parse
方法或者Get*Struct
方法,具体方法定义请参考API文档: https://pkg.go.dev/github.com/gogf/gf/v2/net/ghttp#Request
参数映射
默认规则
客户端提交的参数如果需要映射到服务端定义的struct
属性上,可以采用默认的映射关系,这一点非常方便。默认的转换规则如下:
struct
中需要匹配的属性必须为公开属性
(首字母大写)。- 参数名称会自动按照
不区分大小写
且 忽略-/_/空格
符号 的形式与struct
属性进行匹配。 - 如果匹配成功,那么将键值赋值给属性,如果无法匹配,那么忽略该键值。
以下是几个匹配的示例:
Code Block | ||
---|---|---|
| ||
map键名 struct属性 是否匹配 name Name match Email Email match nickname NickName match NICKNAME NickName match Nick-Name NickName match nick_name NickName match nick name NickName match NickName Nick_Name match Nick-name Nick_Name match nick_name Nick_Name match nick name Nick_Name match |
Tip |
---|
由于底层对象转换实现使用的是 |
自定义规则
Note |
---|
请在对象属性与参数名字差异较大的业务场景下使用自定义映射规则,否则请使用默认的参数映射规则。因为大量的自定义规则标签会增加代码的维护成本。 |
自定义的参数映射规则可以通过为struct
属性绑定tag
实现,tag
名称可以为p/param/params
。例如:
Code Block | ||
---|---|---|
| ||
type User struct{ Id int Name string Pass1 string `p:"password1"` Pass2 string `p:"password2"` } |
其中我们使用了p
标签来指定该属性绑定的参数名称。password1
参数将会映射到Pass1
属性,password2
将会映射到Pass2
属性上。其他属性采用默认的转换规则即可,无需设置tag
。
Parse
转换
从v1.11
版本开始,我们推荐使用我们同时可以使用Parse
方法来实现struct
的转换,该方法是一个便捷方法,内部会自动进行转换及数据校验,但如果struct
中没有校验tag
的绑定将不会执行校验逻辑。
Note |
---|
从 |
使用示例:
Code Block | ||
---|---|---|
| ||
package main import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" ) type RegisterReq struct { Name string Pass string `p:"password1"` Pass2 string `p:"password2"` } type RegisterRes struct { Code int `json:"code"` Error string `json:"error"` Data interface{} `json:"data"` } func main() { s := g.Server() s.BindHandler("/register", func(r *ghttp.Request) { var req *RegisterReq if err := r.Parse(&req); err != nil { r.Response.WriteJsonExit(RegisterRes{ Code: 1, Error: err.Error(), }) } // ... r.Response.WriteJsonExit(RegisterRes{ Data: req, }) }) s.SetPort(8199) s.Run() } |
在该示例中,我们定义了两个结构体:RegisterReq
用于参数接收,RegisterRes
用于数据返回。
其中,我们使用r.Parse(&req)
将客户端提交的参数转换为RegisterReq
对象,当转换成功时req
变量将会被初始化赋值(默认情况下为nil
),否则该方法返回err
并且req
变量为nil
。返回数据结构通过RegisterRes
定义,并且返回格式为JSON
,通过r.Response.WriteJsonExit
实现,该方法将RegisterRes
根据其内部定义的json
标签转换为JSON
格式并退出当前服务方法,不再执行该服务方法的后续逻辑。
为了演示测试效果,这里在正常的返回结果Data
属性中将RegisterReq
对象返回,由于该对象没有绑定json
标签,因此返回的JSON
字段将会为其属性名称。
执行后,我们通过curl
工具来测试一下:
Code Block | ||
---|---|---|
| ||
$ curl "http://127.0.0.1:8199/register?name=john&password1=123&password2=456" {"code":0,"error":"","data":{"Name":"john","Pass":"123","Pass2":"456"}} $ curl -d "name=john&password1=123&password2=456" -X POST "http://127.0.0.1:8199/register" {"code":0,"error":"","data":{"Name":"john","Pass":"123","Pass2":"456"}} |
我们使用了GET
和POST
两种提交方式来做测试,可以看到服务端都能完美地获取到提交参数并完成对象转换。
Panel | ||
---|---|---|
| ||
|