I'm using Go 1.17 with Gin. Here is my struct:
package model
type Movie struct {
ID string `json:"id"`
Year uint16 `json:"year" binding:"required,lt=3000"`
RentNumber uint32 `json:"rent_number" db:"rent_number" binding:"required,lt=4294967290"`
Title string `json:"title" binding:"required,max=255"`
Author string `json:"author" binding:"required,max=80"`
Editor string `json:"editor" binding:"required,max=125"`
Index string `json:"index" binding:"required,max=125"`
Bib string `json:"bib" binding:"required,max=20"`
Ref string `json:"ref" binding:"required,max=20"`
Cat1 string `json:"cat_1" db:"cat_1" binding:"required,max=20"`
Cat2 string `json:"cat_2" db:"cat_2" binding:"required,max=10"`
}
I have a problem to use this struct in a certain handler. In this handler I just need to use 2 properties (Title and Year) from my movie struct. If I'm doing something like this:
func (h *Handler) myHandler(c *gin.Context) {
var movie model.Movie
if err := c.ShouldBindJSON(&movie); err != nil {
c.Error(err)
c.Abort()
return
}
...
It will not working because on this web service I'll send only 2 properties and I'll get the required errors from the binding tags:
{
"title": My title",
"year": 2017
}
So I want to know what is the "go way" to handle this ? I can see 3 solutions.
Use the movie struct and ignoring all fields except
Title
andYear
, but how I can do that ?Create a specific struct with just the needed fields. In this case I'll not place this struct in the model package but in my movie api package
type StructForTheSpecialHandler struct { Year uint16 `json:"year" binding:"required,lt=3000"` Title string `json:"title" binding:"required,max=255"` }
Create the struct directly in my handler like this:
func (h *Handler) myHandler(c *gin.Context) { var tmp struct { Year uint16 `json:"year" binding:"required,lt=3000"` Title string `json:"title" binding:"required,max=255"` } if err := c.ShouldBindJSON(&tmp); err != nil { c.Error(err) c.Abort() return } ...
Can you tell me if you have a better solution or tell me what is the right way between my 3 solutions?
CodePudding user response:
You could just unmarshal it directly (bypassing the validation completely):
err := json.NewDecoder(c.Request.Body).Decode(&movie)
Or you could try to embed those properties in the struct:
type EmbeddedMovieFields struct {
Year uint16 `json:"year" binding:"required,lt=3000"`
Title string `json:"title" binding:"required,max=255"`
}
type Movie struct {
EmbeddedMovieFields
ID string `json:"id"`
RentNumber uint32 `json:"rent_number" db:"rent_number" binding:"required,lt=4294967290"`
Author string `json:"author" binding:"required,max=80"`
Editor string `json:"editor" binding:"required,max=125"`
Index string `json:"index" binding:"required,max=125"`
Bib string `json:"bib" binding:"required,max=20"`
Ref string `json:"ref" binding:"required,max=20"`
Cat1 string `json:"cat_1" db:"cat_1" binding:"required,max=20"`
Cat2 string `json:"cat_2" db:"cat_2" binding:"required,max=10"`
}
var movie model.EmbeddedMovieFields
if err := c.ShouldBindJSON(&movie); err != nil {
c.Error(err)
c.Abort()
return
}