问答

gin swag 同一个接口可以传入不同结构体的写法

作者:admin 2021-05-06 我要评论

使用gin开发一个账号注册接口,Facebook/Google以后还会更多,页面都递交到同一个接口,他们递交的JSON数据,除了 setting 字段,其他的结构都是一样的,如下: /...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

使用gin开发一个账号注册接口,Facebook/Google以后还会更多,页面都递交到同一个接口,他们递交的JSON数据,除了setting字段,其他的结构都是一样的,如下:

// facebook

{
    "username":"facebook",
    "password:"123456",
    "setting": {
        "create_from":"US",
        "is_z":false,
        "use":"MD5"
    }
}

// Google

{
    "username":"google",
    "password":"111111",
    "setting":{
        "enable_two_step":1,
        "enable_gmail":1,
        "enable_ps":1
    }
}

表结构设计如下, 字段 setting 是直接存放了JSON数据格式

CREATE TABLE users (
    id int not null auto_increment,
    user_name varchar(60) not null,
    password char(32) not null,
    setting text not null comment 'JSON方式存储'
)

现在想到的一个方式就是,gin定义一个接口

type ReqBase struct {
    UserName string `json:"username" form:"user_name"`
    Password string `json:"password" form:"password"`
    Setting interface{} `json:"setting" form:"setting"`
}

type Req struct {
    ReqBase
    Setting interface{} `json:"setting" form:"setting"`
}

type ReqFacebook struct {
    ReqBase
    Setting FbSetting `json:"setting" form:"setting"`
}

type ReqGoogle struct {
    ReqBase
    Setting GgSetting `json:"setting" form:"setting"`
}


type FbSetting struct {
    CreateFrom string `json:"create_from" form:"create_from"`
    IsZ string `json:"is_z" form:"is_z"`
    Use string `json:"use" form:"use"`
}

type GgSetting struct {
    EnableTwoStep int `json:"enable_two_step" form:"enable_two_step"`
    EnableGmail int `json:"enable_gmail" form:"enable_gmail"`
    EnablePs int `json:"enable_ps" form:"enable_ps"`
}

定义接收的controller

// @Router /api/user/create [post]
// @Summary 注册
// @Tags /api/user
// @Accept json
// @Produce json
// @Param post body dto.ReqFacebook true "参数 json"
// @Param post body dto.ReqGoogle true "参数 json"
// @Success 200 "{"code": 200, "message": "success" }"
func (s *ctrl) Create(ctx *gin.Context) {
    reqFb := &dto.ReqFacebook{}
    reqGg := &dto.ReqGoogle{}
    if errFb := ctx.ShouldBindBodyWith(&reqFb, binding.JSON); errFb == nil {
        fmt.Println("facebook")
    } else if errGg := ctx.ShouldBindBodyWith(&reqGg, binding.JSON); errGg == nil {
        fmt.Println("google")
    } else {
        fmt.Println("error param")
        return
    }
    
    req := &dto.Req{}
    // logical code ...
    convertStruct(reqFb,&req)
    saveToDb(&req)
}

存在两个问题:

  • 支持同一个接口,可以传入不同结构体的数据,可问生成swag文档的时候,@Param 只支持一个? 而不能像 @Success 描述一样多个。
  • 每次都需要进行一次判断,再转化成规定格式,进入逻辑的处理里面又再次解出。

提问:

  • swag 如何可以让参数定义成多个不同类型的
  • 关于golang中的结构体的转换,比如他们就只有一个setting字段结构不一样,但实际上是最后以text的方式保存进去。怎么样设计更好。一定非得拆成多个接口吗?不同传入结构体不同的接口?
###

接口这样设计不合适,对客户端与服务端以后的扩展也不好,你可以直接使用增加一个定义类型字段与多个配置.根据typ类型来选取需要取值的结构体

type ReqBase struct {
    UserName  string    `json:"username" form:"user_name" binding:"required"`
    Password  string    `json:"password" form:"password" binding:"required"`
    Typ       string    `json:"typ" form:"typ" binding:"required"` // 类型:google=谷歌,facebook=脸书
    GgSetting FbSetting `json:"google_setting,omitempty" form:"google_setting" `
    FbSetting GgSetting `json:"facebook_setting,omitempty" form:"facebook_setting"`
}

type FbSetting struct {
    CreateFrom string `json:"create_from" form:"create_from"`
    IsZ        string `json:"is_z" form:"is_z"`
    Use        string `json:"use" form:"use"`
}

type GgSetting struct {
    EnableTwoStep int `json:"enable_two_step" form:"enable_two_step"`
    EnableGmail   int `json:"enable_gmail" form:"enable_gmail"`
    EnablePs      int `json:"enable_ps" form:"enable_ps"`
}
{
    "username":"facebook",
    "password:"123456",
    "type":"google"
    "google_setting": {
        "enable_two_step":0,
        "enable_gmail":0,
        "enable_ps":0
    }
    "facebook_setting": {
        "create_from":"",
        "is_z":false,
        "use":"MD5"
    }
}
###

第二个问题可以考虑这个方法:
setting单独指定成一个struct,然后这个struct实现UnmarshalJSON方法,这个里面统一处理setting里的内容,可以直接保存起来,也可以让他不参与反序列化,只反序列化其他字段,setting直接以字节形式往后面流程走。

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • gin swag 同一个接口可以传入不同结构

    gin swag 同一个接口可以传入不同结构

  • netty中客户端发送消息到不了服务端

    netty中客户端发送消息到不了服务端

  • dubbo项目开源多久了?

    dubbo项目开源多久了?

  • element UI Notification  如何往自定

    element UI Notification 如何往自定

腾讯云代理商
海外云服务器