需求场景:
文章列表接口: /articles
接口所需字段:文章id、文章标题、文章图片
文章详情接口: /articles/id
接口所需字段:文章id、文章标题、文章图片、文章详情
代码实现:
技术选型:模型转换函数使用copier
package model
type Article struct {
ID int
Title string
ImageUrl string
Content string
}
package response
type Article struct {
ID int `json:"id"`
Title string `json:"title"`
ImageUrl string `json:"imageUrl"`
Content string `json:"content"`
}
type Article struct {}
func (ctr *Article) List(c *gin.Context) {
articles := []*model.Article {
{ID:1, Title: "标题1", Content: "内容1", ImageUrl: "1.jpg"},
{ID:2, Title: "标题2", Content: "内容2", ImageUrl: "2.jpg"},
}
var response []*response.Article
copier.Copy(&response, articles)
c.JSON(http.StatusOK, gin.H{"data": response})
}
func (ctr *Article) Detail(c *gin.Context) {
article := &model.Article{ID:1, Title: "标题1", Content: "内容1", ImageUrl: "1.jpg"}
var response response.Article
copier.Copy(&response, article)
c.JSON(http.StatusOK, gin.H{"data": response})
}
复制代码
以上代码实现方式会导致文章列表接口的文章详情也会对外展示。
在项目开发中,你一定遇到这种场景,同样的模型这个接口需要全部数据字段,另外的接口只需要部分数据字段,还有的场景有些数据字段比较敏感,只能对某些接口展示;比较暴力的方式就是每一个接口建立对应的response模型,这种方式在Java开发中非常常见,那么在Go语言开发中有没有更好的解决方式呢?
网上有很多文章介绍有多种方式如何隐藏字段,如下:
方式一:
type ArticleList struct {
Article
Content string `json:"-"`
}
返回结果如下,content字段只是为空,不隐藏
{
"data": [
{
"id": 1,
"title": "标题1",
"imageUrl": "1.jpg",
"content": ""
},
{
"id": 2,
"title": "标题2",
"imageUrl": "2.jpg",
"content": ""
}
]
}
方式二:
type Omit *struct{}
type ArticleList struct {
Article
Content Omit `json:"content,omitempty"`
}
返回结果如下,content字段变成了json对象,不隐藏,omitempty零值隐藏
{
"data": [
{
"id": 1,
"title": "标题1",
"imageUrl": "1.jpg",
"content": {}
},
{
"id": 2,
"title": "标题2",
"imageUrl": "2.jpg",
"content": {}
}
]
}
复制代码
解决这个问题也经历了很长时间,刚开始也是模仿java的方式,每一个接口建立对应的response模型,后来无意间发现了比较简单的方法可以优雅的隐藏字段,代码如下:
type ArticleList struct {
Article
Content string `json:"content,omitempty" copier:"-"`
}
复制代码
实现原理:copier模型转换会忽略标签"-"的字段,导致目标字段为零值,再通过omitempty零值隐藏,从而实现对象字段隐藏.
如何实现复合结构体的字段隐藏,代码如下:
package model
type Article struct {
ID int
Title string
ImageUrl string
Content string
Author *Author
}
package model
type Author struct {
ID int
Name string
Desc string
}
package response
type Author struct {
ID int `json:"id"`
Name string `json:"name"`
Desc string `json:"desc"`
}
type ArticleListAuthor struct {
Author
Desc string `json:"desc,omitempty" copier:"-"`
}
package response
type Article struct {
ID int `json:"id"`
Title string `json:"title"`
ImageUrl string `json:"imageUrl"`
Content string `json:"content"`
}
type ArticleList struct {
Article
Content string `json:"content,omitempty" copier:"-"`
ArticleListAuthor `json:"author"`
}
复制代码
项目开发过程中,不需要这么死板,如果一个模型有很多属性,只需要对外展示两三个字段,用上述方式需要隐藏大多数属性,还不如直接建立一个新的模型,只包含所需要对外展示的少数字段,灵活度大家自己把握。