0
votes

I'm currently learning GO and I wanted to replicate one of the services we are running in production using GO for training. I'm working with the framework GIN and I need to validate a simple struct like this. It is posted to the search endpoint

type SearchData struct {
    Field1           string `json:"field1,omitempty"`
    Field2           string `json:"field2,omitempty"`
    Field3           string `json:"field,omitempty" binding:"alphanum"`
}

first problem: I can't check if Field3 != nil because is a string, one solution I found by reading online is that I can cast it as a pointer, the problem is that then I get an error from the binding alphanum because nil fail the validation.

second problem: I can remove the omitempty check but if I do so the alphanum validator fail and the fields are set to their default value "". I can't check if the user want to submit "" or is the bindingJSON method that is setting the default value.

By reading online I see that there isn't a proper solution to this problem (or maybe yes), as I'm new to GO I will be happy to see how other people handle this in published / production APIs.

EDIT: This is how I parse the json

func Search(c *gin.Context) {
    db := c.MustGet("db").(*mgo.Database)
    var json SearchData

    if err := c.ShouldBindJSON(&json); err != nil {
        fmt.Println(err)
        utils.ReturnError400(c, "Invalid")
        return
    }

        // the json is used here
}
1
I changed them before posting the struct here, they all start with the uppercase in my code - FakeAccount
is a generic example for a problem that I'm currently facing, the field name is not relevant currently but I will fix the naming in the question thanks - FakeAccount

1 Answers

1
votes

Gin return an empty string if the parameter was not provided. You can use the following method in order to verify if the string is provided:

// IsBlank is delegated to verify that the does not contains only empty char
func IsBlank(str string) bool {
    // Check length
    if len(str) > 0 {
        // Iterate string
        for i := range str {
            // Check about char different from whitespace
            if str[i] > 32 {
                return false
            }
        }
    }
    return true
}

You can read some useful utils method in this repository in order to validate string and execute common task on string:
https://github.com/alessiosavi/GoGPUtils/blob/master/string/stringutils.go

For the second problem, you can use the DefaultQuery in order to set a predefined value if no one are provided, here an example

func get() gin.HandlerFunc {
    fn := func(c *gin.Context) {
        // firstname will be "NOT_PRESENT" if the user does not send the parameter
        firstname := c.DefaultQuery("test", "NOT_PRESENT")
        lastname := c.Query("test1")
        fmt.Println(firstname, lastname)

    }
    return gin.HandlerFunc(fn)
}

Here the documentation about DefaultQuery:
https://godoc.org/github.com/gin-gonic/gin#Context.DefaultQuery