为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 JSON 响应中过滤数据库中的字段?

如何在 JSON 响应中过滤数据库中的字段?

Go
蓝山帝景 2022-01-10 11:01:06
我正在 golang 中制作一个 REST API,我想添加对过滤字段的支持,但我不知道实现它的最佳方法,假设我有这个表示Album模型的结构type Album struct {  ID            uint64    `json:"id"`  User          uint64    `json:"user"`  Name          string    `json:"name"`  CreatedDate   time.Time `json:"createdDate"`  Privacy       string    `json:"privacy"`  Stars         int       `json:"stars"`  PicturesCount int       `json:"picturesCount"`}和一个返回一个实例的函数 Albumfunc GetOne(id uint64, user uint64) (Album, error) {  var album Album  sql := `SELECT * FROM "album" WHERE "id" = $1 AND "user" = $2;`  err := models.DB.QueryRow(sql, id, user).Scan(    &album.ID,    &album.User,    &album.Name,    &album.CreatedDate,    &album.Privacy,    &album.Stars,    &album.PicturesCount,  )  return album, err}客户要发出这样的请求https://api.localhost.com/albums/1/?fields=id,name,privacy抛开明显的安全问题不谈,我的第一个想法是使用类似这样的方法过滤数据库中的字段func GetOne(id uint64, user uint64, fields string) {  var album Album  sql := fmt.Sprintf(`SELECT %s FROM "album" WHERE "id" = $1 AND "user" = $2;`, fields)  // i don't know what to do after this}然后我想omitempty在所有字段中添加标签并将字段设置为零值,然后再将其编码为 JSON,这行得通吗?哪个是更好的方法?有没有最好的方法?我将如何实施第一种方法?谢谢你。
查看完整描述

1 回答

?
郎朗坤

TA贡献1921条经验 获得超9个赞

对于您的第一个提案(仅查询请求的字段),有两种方法(回答“这可行吗?”和“我将如何实施第一种方法?”):

  1. 动态地创建一个(可能是匿名的)struct并使用encoding/json.

  2. 实现一个包装器,它将*database/sql.Rows您从查询中返回的内容转换为 JSON。

对于方法(1.),您将需要以某种方式struct为原始属性的任何组合创建s struct。由于reflect无法在运行时创建新的结构类型,您唯一的机会就是在编译时生成它们。组合爆炸会使你的二进制文件膨胀,所以不要那样做。

方法(2.)应谨慎处理,只能作为最后的手段。获取请求字段列表并使用从 DB 获得的值写出 JSON 听起来很简单,并且不涉及反射。但是,您的解决方案将(很可能)比encoding/json.

在阅读您的问题时,我也考虑过使用json:"omitempty"struct 标签。我认为这是更可取的解决方案。它既不涉及元编程也不涉及编写自己的 JSON 编码器,这是一件好事。请注意在某些字段丢失的情况下的影响(客户端可能必须考虑这一点)。您可以始终查询所有属性并使用反射覆盖不需要的属性。

最后,上述所有解决方案都是次优的,最好的解决方案是根本不实现该功能。我希望您有充分的理由使属性可变,我很高兴根据您的解释进一步澄清我的答案。但是,如果资源的其中一个属性太大,它可能应该是子资源。


查看完整回答
反对 回复 2022-01-10
  • 1 回答
  • 0 关注
  • 250 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号