server.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. package main
  2. import (
  3. "net/http"
  4. "reflect"
  5. "github.com/gin-gonic/gin"
  6. "github.com/gin-gonic/gin/binding"
  7. validator "gopkg.in/go-playground/validator.v8"
  8. )
  9. // User contains user information.
  10. type User struct {
  11. FirstName string `json:"fname"`
  12. LastName string `json:"lname"`
  13. Email string `binding:"required,email"`
  14. }
  15. // UserStructLevelValidation contains custom struct level validations that don't always
  16. // make sense at the field validation level. For example, this function validates that either
  17. // FirstName or LastName exist; could have done that with a custom field validation but then
  18. // would have had to add it to both fields duplicating the logic + overhead, this way it's
  19. // only validated once.
  20. //
  21. // NOTE: you may ask why wouldn't not just do this outside of validator. Doing this way
  22. // hooks right into validator and you can combine with validation tags and still have a
  23. // common error output format.
  24. func UserStructLevelValidation(v *validator.Validate, structLevel *validator.StructLevel) {
  25. user := structLevel.CurrentStruct.Interface().(User)
  26. if len(user.FirstName) == 0 && len(user.LastName) == 0 {
  27. structLevel.ReportError(
  28. reflect.ValueOf(user.FirstName), "FirstName", "fname", "fnameorlname",
  29. )
  30. structLevel.ReportError(
  31. reflect.ValueOf(user.LastName), "LastName", "lname", "fnameorlname",
  32. )
  33. }
  34. // plus can to more, even with different tag than "fnameorlname"
  35. }
  36. func main() {
  37. route := gin.Default()
  38. if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
  39. v.RegisterStructValidation(UserStructLevelValidation, User{})
  40. }
  41. route.POST("/user", validateUser)
  42. route.Run(":8085")
  43. }
  44. func validateUser(c *gin.Context) {
  45. var u User
  46. if err := c.ShouldBindJSON(&u); err == nil {
  47. c.JSON(http.StatusOK, gin.H{"message": "User validation successful."})
  48. } else {
  49. c.JSON(http.StatusBadRequest, gin.H{
  50. "message": "User validation failed!",
  51. "error": err.Error(),
  52. })
  53. }
  54. }