计划重构我们去年建立的应用程序的代码库。让我们说这个api端点w / c支持包括相关资源GET /api/leagues?include=sport
。是否有更简洁的方法可以在api响应中使sport
资源的league
属性动态化? sport属性的值可以是int或Sport结构。目前,这就是我们正在做的事情:
// models/league.go
type League struct {
SportId int64 `json:"-"`
Sport Sport `json:"-"`
SportWrapper interface{} `json:"sport"`
}
// controllers/league.go
include := c.Request.URL.Query().Get("include")
includes := strings.Split(include, ",")
for _, include := range includes {
if include == "sport" {
includeSport = true
}
}
if includeSport {
league.SportWrapper = league.Sport
} else {
league.SportWrapper = league.SportId
}
c.JSON(http.StatusOK, league)
对api请求的回应:
{
sport: {
id: <id>,
name: <name>
}
}
它也可以是:
{
sport: <sport_id>
}
答案 0 :(得分:1)
没有更多背景,很难说。我假设SportId也是Sport结构的一部分。您基本上只返回ID或整个结构。
我建议只添加
Sport Sport `json:"-"`
结构。而不是直接将其序列化为json,您必须首先使用固定属性集创建一个映射(基本上是一个视图模型)。在那里你可以设置你的SportID或Sport结构,之后你可以将地图序列化为json。
这也不是一个非常好的解决方案,但优势在于,在您当前的解决方案中,响应代码的丑陋会泄漏到数据模型中,从而泄漏到应用程序的其余部分。使用中间映射,丑陋的部分被限制在响应生成中。
// models/league.go
type League struct {
Sport Sport
}
... parse includes ...
viewModel := map[string]interface{}
if includeSport {
viewModel["sport"] = league.Sport
} else {
viewModel["sport"] = league.Sport.ID
}
c.JSON(http.StatusOK, viewModel)
答案 1 :(得分:0)
// models/league.go
type League struct {
SportID int64 `json:"-"`
Sport Sport `json:"-"`
SportWrapper interface{} `json:"sport"`
}
var (
sportID int
sport Sport
)
// controllers/league.go
include := c.Request.URL.Query().Get("include")
if err := json.Unmarshal([]byte(unclude), &sportID); err != nil {
json.Unmarshal([]byte(unclude), &sport)
league.SportWrapper = sport
league.Sport = sport
} else {
league.SportWrapper = sportID
league.SportID = sportID
}
c.JSON(http.StatusOK, league)
如果你可以将你的请求参数设置为json,你可以使用它。