├── .gitignore
├── static
├── style.css
├── index.html
└── app.js
├── README.md
├── go.mod
├── main.go
└── go.sum
/.gitignore:
--------------------------------------------------------------------------------
1 | go-ozzo-validation-example
2 | *.exe
3 |
--------------------------------------------------------------------------------
/static/style.css:
--------------------------------------------------------------------------------
1 | #message {
2 | color: red;
3 | }
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # go-ozzo-validation-example
2 |
3 | Example app using labstack/echo and ozzo-validator.
4 |
5 | ## Build
6 |
7 | ```
8 | $ go build
9 | $ ./go-ozzo-validation-example
10 | ```
11 |
12 | ## License
13 |
14 | MIT
15 |
16 | ## Author
17 |
18 | Yasuhiro Matsumoto (a.k.a. mattn)
19 |
--------------------------------------------------------------------------------
/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | example
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/mattn/go-ozzo-validation-example
2 |
3 | go 1.18
4 |
5 | require (
6 | github.com/go-ozzo/ozzo-validation/v4 v4.3.0
7 | github.com/labstack/echo/v4 v4.11.4
8 | )
9 |
10 | require (
11 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
12 | github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
13 | github.com/labstack/gommon v0.4.2 // indirect
14 | github.com/mattn/go-colorable v0.1.13 // indirect
15 | github.com/mattn/go-isatty v0.0.20 // indirect
16 | github.com/valyala/bytebufferpool v1.0.0 // indirect
17 | github.com/valyala/fasttemplate v1.2.2 // indirect
18 | golang.org/x/crypto v0.17.0 // indirect
19 | golang.org/x/net v0.19.0 // indirect
20 | golang.org/x/sys v0.15.0 // indirect
21 | golang.org/x/text v0.14.0 // indirect
22 | golang.org/x/time v0.5.0 // indirect
23 | )
24 |
--------------------------------------------------------------------------------
/static/app.js:
--------------------------------------------------------------------------------
1 | window.addEventListener('DOMContentLoaded', () => {
2 | document.querySelector('#submit').addEventListener('click', () => {
3 | axios.post('/api', {
4 | name: document.querySelector('#name').value,
5 | email: document.querySelector('#email').value,
6 | content: document.querySelector('#content').value,
7 | }, {
8 | headers: {'Content-Type': 'application/json'},
9 | responseType: 'json',
10 | })
11 | .then((response) => {
12 | document.querySelector('#message').textContent = '';
13 | document.querySelector('#name').value = '';
14 | document.querySelector('#email').value = '';
15 | document.querySelector('#content').value = '';
16 | })
17 | .catch((error) => {
18 | document.querySelector('#message').textContent = error.response.data.error;
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "embed"
5 | "errors"
6 | "fmt"
7 | "net/http"
8 | "regexp"
9 | "strings"
10 |
11 | validation "github.com/go-ozzo/ozzo-validation/v4"
12 | "github.com/go-ozzo/ozzo-validation/v4/is"
13 | "github.com/labstack/echo/v4"
14 | "github.com/labstack/echo/v4/middleware"
15 | )
16 |
17 | type Comment struct {
18 | Name string `json:"name"`
19 | Email string `json:"email"`
20 | Content string `json:"content"`
21 | }
22 |
23 | type CustomValidator struct{}
24 |
25 | func (cv *CustomValidator) Validate(i interface{}) error {
26 | if c, ok := i.(validation.Validatable); ok {
27 | return c.Validate()
28 | }
29 | return nil
30 | }
31 |
32 | func (a Comment) Validate() error {
33 | return validation.ValidateStruct(&a,
34 | validation.Field(
35 | &a.Name,
36 | validation.Required.Error("名前は必須入力です"),
37 | validation.RuneLength(5, 20).Error("名前は {min}~{max} 文字です"),
38 | is.PrintableASCII.Error("名前はASCIIで入力して下さい"),
39 | ),
40 | validation.Field(
41 | &a.Email,
42 | validation.Required.Error("メールアドレスは必須入力です"),
43 | validation.RuneLength(5, 40).Error("メールアドレスは {min}~{max} 文字です"),
44 | is.Email.Error("メールアドレスを入力して下さい"),
45 | ),
46 | validation.Field(
47 | &a.Content,
48 | validation.Required.Error("本文は必須入力です"),
49 | validation.RuneLength(5, 50).Error("本文は {min}~{max} 文字です"),
50 | ),
51 | )
52 | }
53 |
54 | //go:embed static
55 | var localFS embed.FS
56 |
57 | func main() {
58 | e := echo.New()
59 | e.Debug = true
60 | e.Validator = &CustomValidator{}
61 | e.Use(middleware.Logger())
62 | e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
63 | Root: "static",
64 | Filesystem: http.FS(localFS),
65 | }))
66 |
67 | e.POST("/api", func(c echo.Context) error {
68 | var comment Comment
69 | if err := c.Bind(&comment); err != nil {
70 | return err
71 | }
72 | if err := c.Validate(comment); err != nil {
73 | errs := err.(validation.Errors)
74 | re := regexp.MustCompile(`{[a-z]+}`)
75 | for k, err := range errs {
76 | c.Logger().Error(k + ": " + err.Error())
77 | verr := err.(validation.Error)
78 | params := verr.Params()
79 | errs[k] = errors.New(re.ReplaceAllStringFunc(verr.Message(), func(s string) string {
80 | return fmt.Sprint(params[strings.Trim(s, "{}")])
81 | }))
82 | }
83 | return errs
84 | }
85 | return c.JSON(http.StatusOK, &struct {
86 | Result string `json:"result"`
87 | }{
88 | Result: "OK",
89 | })
90 | })
91 | e.Logger.Fatal(e.Start(":8989"))
92 | }
93 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
2 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
3 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
6 | github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
7 | github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
8 | github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
9 | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
10 | github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
11 | github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
12 | github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
13 | github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
14 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
15 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
16 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
17 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
18 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
19 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
20 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
21 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
22 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
23 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
24 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
25 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
26 | github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
27 | github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
28 | golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
29 | golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
30 | golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
31 | golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
32 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
33 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
34 | golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
35 | golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
36 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
37 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
38 | golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
39 | golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
40 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
41 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
42 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
43 |
--------------------------------------------------------------------------------