mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-02-26 23:48:55 -06:00
chore: move go-ozzo/ozzo-validation to invopop/validation
invpop/validation is a fork of go-ozzo/ozzo-validation with some additional bug fixes. Specifically we need: https://github.com/invopop/validation/pull/1
This commit is contained in:
committed by
Ralf Haferkamp
parent
1b47707e2f
commit
90f7cc23f4
2
go.mod
2
go.mod
@@ -41,7 +41,6 @@ require (
|
||||
github.com/go-micro/plugins/v4/wrapper/breaker/gobreaker v1.2.0
|
||||
github.com/go-micro/plugins/v4/wrapper/monitoring/prometheus v1.2.0
|
||||
github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry v1.2.0
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
|
||||
github.com/go-playground/validator/v10 v10.20.0
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||
@@ -52,6 +51,7 @@ require (
|
||||
github.com/gookit/config/v2 v2.2.5
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
|
||||
github.com/invopop/validation v0.3.0
|
||||
github.com/jellydator/ttlcache/v2 v2.11.1
|
||||
github.com/jellydator/ttlcache/v3 v3.2.0
|
||||
github.com/jinzhu/now v1.1.5
|
||||
|
||||
6
go.sum
6
go.sum
@@ -871,7 +871,7 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
|
||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aws/aws-sdk-go v1.37.27/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
@@ -1232,8 +1232,6 @@ github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry v1.2.0 h1:e2hgtWMNqJ3
|
||||
github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry v1.2.0/go.mod h1:BBqL7ckGNb7rFfk3vU2Yj/CILVsz/WF19CkAyveQl8A=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
|
||||
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
|
||||
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
@@ -1546,6 +1544,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
|
||||
github.com/invopop/validation v0.3.0 h1:o260kbjXzoBO/ypXDSSrCLL7SxEFUXBsX09YTE9AxZw=
|
||||
github.com/invopop/validation v0.3.0/go.mod h1:qIBG6APYLp2Wu3/96p3idYjP8ffTKVmQBfKiZbw0Hts=
|
||||
github.com/jarcoal/httpmock v1.0.6/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"errors"
|
||||
"regexp"
|
||||
|
||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||
"github.com/go-ozzo/ozzo-validation/v4/is"
|
||||
validation "github.com/invopop/validation"
|
||||
"github.com/invopop/validation/is"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
)
|
||||
@@ -129,12 +129,12 @@ func validateListRoleAssignmentsFiltered(req *settingssvc.ListRoleAssignmentsFil
|
||||
}
|
||||
|
||||
func validateUserRoleAssignmentFilter(values interface{}) error {
|
||||
filter, ok := values.(settingsmsg.UserRoleAssignmentFilter)
|
||||
filter, ok := values.(*settingsmsg.UserRoleAssignmentFilter)
|
||||
if !ok {
|
||||
return errors.New("expected UserRoleAssignmentFilter")
|
||||
}
|
||||
return validation.ValidateStruct(
|
||||
&filter,
|
||||
filter,
|
||||
validation.Field(&filter.Type,
|
||||
validation.Required,
|
||||
validation.In(settingsmsg.UserRoleAssignmentFilter_TYPE_ACCOUNT, settingsmsg.UserRoleAssignmentFilter_TYPE_ROLE),
|
||||
|
||||
@@ -1,49 +1,54 @@
|
||||
# ozzo-validation
|
||||
# Go Validation
|
||||
|
||||
[](http://godoc.org/github.com/go-ozzo/ozzo-validation)
|
||||
[](https://travis-ci.org/go-ozzo/ozzo-validation)
|
||||
[](https://coveralls.io/github/go-ozzo/ozzo-validation?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/go-ozzo/ozzo-validation)
|
||||
[](https://github.com/invopop/validation/actions/workflows/lint.yaml)
|
||||
[](https://github.com/invopop/validation/actions/workflows/test.yaml)
|
||||
[](http://godoc.org/github.com/invopop/validation)
|
||||
[](https://coveralls.io/github/invopop/validation?branch=main)
|
||||
[](https://goreportcard.com/report/github.com/invopop/validation)
|
||||

|
||||
|
||||
NOTE: This is a fork of the well known [ozzo-validation](https://github.com/go-ozzo/ozzo-validation) package which as of Feb 2023 doesn't appear to be under active maintenance for more than 2 years. At [Invopop](https://invopop.com) we use this library extensively, so it only felt appropriate to be more pro-active. We'll do out best to respond to issues and review or merge any pull requests.
|
||||
|
||||
## Description
|
||||
|
||||
ozzo-validation is a Go package that provides configurable and extensible data validation capabilities.
|
||||
validation is a Go package that provides configurable and extensible data validation capabilities.
|
||||
|
||||
It has the following features:
|
||||
|
||||
* use normal programming constructs rather than error-prone struct tags to specify how data should be validated.
|
||||
* can validate data of different types, e.g., structs, strings, byte slices, slices, maps, arrays.
|
||||
* can validate custom data types as long as they implement the `Validatable` interface.
|
||||
* can validate data types that implement the `sql.Valuer` interface (e.g. `sql.NullString`).
|
||||
* customizable and well-formatted validation errors.
|
||||
* error code and message translation support.
|
||||
* provide a rich set of validation rules right out of box.
|
||||
* extremely easy to create and use custom validation rules.
|
||||
- use normal programming constructs rather than error-prone struct tags to specify how data should be validated.
|
||||
- can validate data of different types, e.g., structs, strings, byte slices, slices, maps, arrays.
|
||||
- can validate custom data types as long as they implement the `Validatable` interface.
|
||||
- can validate data types that implement the `sql.Valuer` interface (e.g. `sql.NullString`).
|
||||
- customizable and well-formatted validation errors.
|
||||
- error code and message translation support.
|
||||
- provide a rich set of validation rules right out of box.
|
||||
- extremely easy to create and use custom validation rules.
|
||||
|
||||
For an example on how this library is used in an application, please refer to [go-rest-api](https://github.com/qiangxue/go-rest-api) which is a starter kit for building RESTful APIs in Go.
|
||||
|
||||
For further examples, checkout the [GOBL project](https://github.com/invopop/gobl) which uses validation extensively.
|
||||
|
||||
## Requirements
|
||||
|
||||
Go 1.13 or above.
|
||||
|
||||
Go 1.16 or above.
|
||||
|
||||
## Getting Started
|
||||
|
||||
The ozzo-validation package mainly includes a set of validation rules and two validation methods. You use
|
||||
The validation package mainly includes a set of validation rules and two validation methods. You use
|
||||
validation rules to describe how a value should be considered valid, and you call either `validation.Validate()`
|
||||
or `validation.ValidateStruct()` to validate the value.
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
Run the following command to install the package:
|
||||
|
||||
```
|
||||
go get github.com/go-ozzo/ozzo-validation
|
||||
go get github.com/invopop/validation
|
||||
```
|
||||
|
||||
### Validating a Simple Value
|
||||
|
||||
For a simple value, such as a string or an integer, you may use `validation.Validate()` to validate it. For example,
|
||||
For a simple value, such as a string or an integer, you may use `validation.Validate()` to validate it. For example,
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -51,8 +56,8 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-ozzo/ozzo-validation/v4"
|
||||
"github.com/go-ozzo/ozzo-validation/v4/is"
|
||||
"github.com/invopop/validation"
|
||||
"github.com/invopop/validation/is"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -72,13 +77,12 @@ The method `validation.Validate()` will run through the rules in the order that
|
||||
the validation, the method will return the corresponding error and skip the rest of the rules. The method will
|
||||
return nil if the value passes all validation rules.
|
||||
|
||||
|
||||
### Validating a Struct
|
||||
|
||||
For a struct value, you usually want to check if its fields are valid. For example, in a RESTful application, you
|
||||
may unmarshal the request payload into a struct and then validate the struct fields. If one or multiple fields
|
||||
are invalid, you may want to get an error describing which fields are invalid. You can use `validation.ValidateStruct()`
|
||||
to achieve this purpose. A single struct can have rules for multiple fields, and a field can be associated with multiple
|
||||
to achieve this purpose. A single struct can have rules for multiple fields, and a field can be associated with multiple
|
||||
rules. For example,
|
||||
|
||||
```go
|
||||
@@ -91,10 +95,10 @@ type Address struct {
|
||||
|
||||
func (a Address) Validate() error {
|
||||
return validation.ValidateStruct(&a,
|
||||
// Street cannot be empty, and the length must between 5 and 50
|
||||
validation.Field(&a.Street, validation.Required, validation.Length(5, 50)),
|
||||
// City cannot be empty, and the length must between 5 and 50
|
||||
validation.Field(&a.City, validation.Required, validation.Length(5, 50)),
|
||||
// Street cannot be empty, and the length must between 2 and 50
|
||||
validation.Field(&a.Street, validation.Required, validation.Length(2, 50)),
|
||||
// City cannot be empty, and the length must between 2 and 50
|
||||
validation.Field(&a.City, validation.Required, validation.Length(2, 50)),
|
||||
// State cannot be empty, and must be a string consisting of two letters in upper case
|
||||
validation.Field(&a.State, validation.Required, validation.Match(regexp.MustCompile("^[A-Z]{2}$"))),
|
||||
// State cannot be empty, and must be a string consisting of five digits
|
||||
@@ -115,19 +119,18 @@ fmt.Println(err)
|
||||
// Street: the length must be between 5 and 50; State: must be in a valid format.
|
||||
```
|
||||
|
||||
Note that when calling `validation.ValidateStruct` to validate a struct, you should pass to the method a pointer
|
||||
Note that when calling `validation.ValidateStruct` to validate a struct, you should pass to the method a pointer
|
||||
to the struct instead of the struct itself. Similarly, when calling `validation.Field` to specify the rules
|
||||
for a struct field, you should use a pointer to the struct field.
|
||||
for a struct field, you should use a pointer to the struct field.
|
||||
|
||||
When the struct validation is performed, the fields are validated in the order they are specified in `ValidateStruct`.
|
||||
When the struct validation is performed, the fields are validated in the order they are specified in `ValidateStruct`.
|
||||
And when each field is validated, its rules are also evaluated in the order they are associated with the field.
|
||||
If a rule fails, an error is recorded for that field, and the validation will continue with the next field.
|
||||
|
||||
|
||||
### Validating a Map
|
||||
|
||||
Sometimes you might need to work with dynamic data stored in maps rather than a typed model. You can use `validation.Map()`
|
||||
in this situation. A single map can have rules for multiple keys, and a key can be associated with multiple
|
||||
in this situation. A single map can have rules for multiple keys, and a key can be associated with multiple
|
||||
rules. For example,
|
||||
|
||||
```go
|
||||
@@ -150,10 +153,10 @@ err := validation.Validate(c,
|
||||
validation.Key("Email", validation.Required, is.Email),
|
||||
// Validate Address using its own validation rules
|
||||
validation.Key("Address", validation.Map(
|
||||
// Street cannot be empty, and the length must between 5 and 50
|
||||
validation.Key("Street", validation.Required, validation.Length(5, 50)),
|
||||
// City cannot be empty, and the length must between 5 and 50
|
||||
validation.Key("City", validation.Required, validation.Length(5, 50)),
|
||||
// Street cannot be empty, and the length must between 2 and 50
|
||||
validation.Key("Street", validation.Required, validation.Length(2, 50)),
|
||||
// City cannot be empty, and the length must between 2 and 50
|
||||
validation.Key("City", validation.Required, validation.Length(2, 50)),
|
||||
// State cannot be empty, and must be a string consisting of two letters in upper case
|
||||
validation.Key("State", validation.Required, validation.Match(regexp.MustCompile("^[A-Z]{2}$"))),
|
||||
// State cannot be empty, and must be a string consisting of five digits
|
||||
@@ -166,18 +169,17 @@ fmt.Println(err)
|
||||
// Address: (State: must be in a valid format; Street: the length must be between 5 and 50.); Email: must be a valid email address.
|
||||
```
|
||||
|
||||
When the map validation is performed, the keys are validated in the order they are specified in `Map`.
|
||||
When the map validation is performed, the keys are validated in the order they are specified in `Map`.
|
||||
And when each key is validated, its rules are also evaluated in the order they are associated with the key.
|
||||
If a rule fails, an error is recorded for that key, and the validation will continue with the next key.
|
||||
|
||||
|
||||
### Validation Errors
|
||||
|
||||
The `validation.ValidateStruct` method returns validation errors found in struct fields in terms of `validation.Errors`
|
||||
The `validation.ValidateStruct` method returns validation errors found in struct fields in terms of `validation.Errors`
|
||||
which is a map of fields and their corresponding errors. Nil is returned if validation passes.
|
||||
|
||||
By default, `validation.Errors` uses the struct tags named `json` to determine what names should be used to
|
||||
represent the invalid fields. The type also implements the `json.Marshaler` interface so that it can be marshaled
|
||||
By default, `validation.Errors` uses the struct tags named `json` to determine what names should be used to
|
||||
represent the invalid fields. The type also implements the `json.Marshaler` interface so that it can be marshaled
|
||||
into a proper JSON object. For example,
|
||||
|
||||
```go
|
||||
@@ -221,16 +223,15 @@ fmt.Println(err)
|
||||
// email: must be a valid email address; zip: cannot be blank.
|
||||
```
|
||||
|
||||
In the above example, we build a `validation.Errors` by a list of names and the corresponding validation results.
|
||||
At the end we call `Errors.Filter()` to remove from `Errors` all nils which correspond to those successful validation
|
||||
In the above example, we build a `validation.Errors` by a list of names and the corresponding validation results.
|
||||
At the end we call `Errors.Filter()` to remove from `Errors` all nils which correspond to those successful validation
|
||||
results. The method will return nil if `Errors` is empty.
|
||||
|
||||
The above approach is very flexible as it allows you to freely build up your validation error structure. You can use
|
||||
it to validate both struct and non-struct values. Compared to using `ValidateStruct` to validate a struct,
|
||||
it has the drawback that you have to redundantly specify the error keys while `ValidateStruct` can automatically
|
||||
it to validate both struct and non-struct values. Compared to using `ValidateStruct` to validate a struct,
|
||||
it has the drawback that you have to redundantly specify the error keys while `ValidateStruct` can automatically
|
||||
find them out.
|
||||
|
||||
|
||||
### Internal Errors
|
||||
|
||||
Internal errors are different from validation errors in that internal errors are caused by malfunctioning code (e.g.
|
||||
@@ -252,23 +253,22 @@ if err := a.Validate(); err != nil {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Validatable Types
|
||||
|
||||
A type is validatable if it implements the `validation.Validatable` interface.
|
||||
A type is validatable if it implements the `validation.Validatable` interface.
|
||||
|
||||
When `validation.Validate` is used to validate a validatable value, if it does not find any error with the
|
||||
given validation rules, it will further call the value's `Validate()` method.
|
||||
When `validation.Validate` is used to validate a validatable value, if it does not find any error with the
|
||||
given validation rules, it will further call the value's `Validate()` method.
|
||||
|
||||
Similarly, when `validation.ValidateStruct` is validating a struct field whose type is validatable, it will call
|
||||
Similarly, when `validation.ValidateStruct` is validating a struct field whose type is validatable, it will call
|
||||
the field's `Validate` method after it passes the listed rules.
|
||||
|
||||
> Note: When implementing `validation.Validatable`, do not call `validation.Validate()` to validate the value in its
|
||||
> original type because this will cause infinite loops. For example, if you define a new type `MyString` as `string`
|
||||
> and implement `validation.Validatable` for `MyString`, within the `Validate()` function you should cast the value
|
||||
> and implement `validation.Validatable` for `MyString`, within the `Validate()` function you should cast the value
|
||||
> to `string` first before calling `validation.Validate()` to validate it.
|
||||
|
||||
In the following example, the `Address` field of `Customer` is validatable because `Address` implements
|
||||
In the following example, the `Address` field of `Customer` is validatable because `Address` implements
|
||||
`validation.Validatable`. Therefore, when validating a `Customer` struct with `validation.ValidateStruct`,
|
||||
validation will "dive" into the `Address` field.
|
||||
|
||||
@@ -332,8 +332,8 @@ fmt.Println(err)
|
||||
// 0: (City: cannot be blank; Street: cannot be blank.); 2: (Street: cannot be blank; Zip: must be in a valid format.).
|
||||
```
|
||||
|
||||
When using `validation.ValidateStruct` to validate a struct, the above validation procedure also applies to those struct
|
||||
fields which are map/slices/arrays of validatables.
|
||||
When using `validation.ValidateStruct` to validate a struct, the above validation procedure also applies to those struct
|
||||
fields which are map/slices/arrays of validatables.
|
||||
|
||||
#### Each
|
||||
|
||||
@@ -376,14 +376,12 @@ If the pointer is nil, these rules will skip the validation.
|
||||
An exception is the `validation.Required` and `validation.NotNil` rules. When a pointer is nil, they
|
||||
will report a validation error.
|
||||
|
||||
|
||||
### Types Implementing `sql.Valuer`
|
||||
|
||||
If a data type implements the `sql.Valuer` interface (e.g. `sql.NullString`), the built-in validation rules will handle
|
||||
it properly. In particular, when a rule is validating such data, it will call the `Value()` method and validate
|
||||
the returned value instead.
|
||||
|
||||
|
||||
### Required vs. Not Nil
|
||||
|
||||
When validating input values, there are two different scenarios about checking if input values are provided or not.
|
||||
@@ -395,7 +393,6 @@ In the second scenario, an input value is considered missing only if it is not e
|
||||
used in this case so that you can detect if a value is entered or not by checking if the pointer is nil or not.
|
||||
You can use the `validation.NotNil` rule to ensure a value is entered (even if it is a zero value).
|
||||
|
||||
|
||||
### Embedded Structs
|
||||
|
||||
The `validation.ValidateStruct` method will properly validate a struct that contains embedded structs. In particular,
|
||||
@@ -444,10 +441,9 @@ fmt.Println(err)
|
||||
// Level: cannot be blank; Name: cannot be blank.
|
||||
```
|
||||
|
||||
|
||||
### Conditional Validation
|
||||
|
||||
Sometimes, we may want to validate a value only when certain condition is met. For example, we want to ensure the
|
||||
Sometimes, we may want to validate a value only when certain condition is met. For example, we want to ensure the
|
||||
`unit` struct field is not empty only when the `quantity` field is not empty; or we may want to ensure either `email`
|
||||
or `phone` is provided. The so-called conditional validation can be achieved with the help of `validation.When`.
|
||||
The following code implements the aforementioned examples:
|
||||
@@ -455,8 +451,8 @@ The following code implements the aforementioned examples:
|
||||
```go
|
||||
result := validation.ValidateStruct(&a,
|
||||
validation.Field(&a.Unit, validation.When(a.Quantity != "", validation.Required).Else(validation.Nil)),
|
||||
validation.Field(&a.Phone, validation.When(a.Email == "", validation.Required.Error('Either phone or Email is required.')),
|
||||
validation.Field(&a.Email, validation.When(a.Phone == "", validation.Required.Error('Either phone or Email is required.')),
|
||||
validation.Field(&a.Phone, validation.When(a.Email == "", validation.Required.Error("Either phone or Email is required.")),
|
||||
validation.Field(&a.Email, validation.When(a.Phone == "", validation.Required.Error("Either phone or Email is required.")),
|
||||
)
|
||||
```
|
||||
|
||||
@@ -467,8 +463,8 @@ The above code can also be simplified using the shortcut `validation.Required.Wh
|
||||
```go
|
||||
result := validation.ValidateStruct(&a,
|
||||
validation.Field(&a.Unit, validation.Required.When(a.Quantity != ""), validation.Nil.When(a.Quantity == "")),
|
||||
validation.Field(&a.Phone, validation.Required.When(a.Email == "").Error('Either phone or Email is required.')),
|
||||
validation.Field(&a.Email, validation.Required.When(a.Phone == "").Error('Either phone or Email is required.')),
|
||||
validation.Field(&a.Phone, validation.Required.When(a.Email == "").Error("Either phone or Email is required.")),
|
||||
validation.Field(&a.Email, validation.Required.When(a.Phone == "").Error("Either phone or Email is required.")),
|
||||
)
|
||||
```
|
||||
|
||||
@@ -488,16 +484,17 @@ fmt.Println(err)
|
||||
// must be a string with five digits
|
||||
```
|
||||
|
||||
You can also customize the pre-defined error(s) of a built-in rule such that the customization applies to *every*
|
||||
You can also customize the pre-defined error(s) of a built-in rule such that the customization applies to _every_
|
||||
instance of the rule. For example, the `Required` rule uses the pre-defined error `ErrRequired`. You can customize it
|
||||
during the application initialization:
|
||||
|
||||
```go
|
||||
validation.ErrRequired = validation.ErrRequired.SetMessage("the value is required")
|
||||
validation.ErrRequired = validation.ErrRequired.SetMessage("the value is required")
|
||||
```
|
||||
|
||||
### Error Code and Message Translation
|
||||
|
||||
The errors returned by the validation rules implement the `Error` interface which contains the `Code()` method
|
||||
The errors returned by the validation rules implement the `Error` interface which contains the `Code()` method
|
||||
to provide the error code information. While the message of a validation error is often customized, the code is immutable.
|
||||
You can use error code to programmatically check a validation error or look for the translation of the corresponding message.
|
||||
|
||||
@@ -549,10 +546,9 @@ fmt.Println(err)
|
||||
// Output: unexpected string
|
||||
```
|
||||
|
||||
|
||||
### Rule Groups
|
||||
|
||||
When a combination of several rules are used in multiple places, you may use the following trick to create a
|
||||
When a combination of several rules are used in multiple places, you may use the following trick to create a
|
||||
rule group so that your code is more maintainable.
|
||||
|
||||
```go
|
||||
@@ -577,21 +573,19 @@ func (u User) Validate() error {
|
||||
In the above example, we create a rule group `NameRule` which consists of two validation rules. We then use this rule
|
||||
group to validate both `FirstName` and `LastName`.
|
||||
|
||||
|
||||
## Context-aware Validation
|
||||
|
||||
While most validation rules are self-contained, some rules may depend dynamically on a context. A rule may implement the
|
||||
`validation.RuleWithContext` interface to support the so-called context-aware validation.
|
||||
|
||||
To validate an arbitrary value with a context, call `validation.ValidateWithContext()`. The `context.Conext` parameter
|
||||
|
||||
To validate an arbitrary value with a context, call `validation.ValidateWithContext()`. The `context.Conext` parameter
|
||||
will be passed along to those rules that implement `validation.RuleWithContext`.
|
||||
|
||||
To validate the fields of a struct with a context, call `validation.ValidateStructWithContext()`.
|
||||
To validate the fields of a struct with a context, call `validation.ValidateStructWithContext()`.
|
||||
|
||||
You can define a context-aware rule from scratch by implementing both `validation.Rule` and `validation.RuleWithContext`.
|
||||
You can define a context-aware rule from scratch by implementing both `validation.Rule` and `validation.RuleWithContext`.
|
||||
You can also use `validation.WithContext()` to turn a function into a context-aware rule. For example,
|
||||
|
||||
|
||||
```go
|
||||
rule := validation.WithContext(func(ctx context.Context, value interface{}) error {
|
||||
if ctx.Value("secret") == value.(string) {
|
||||
@@ -609,94 +603,94 @@ fmt.Println(err)
|
||||
When performing context-aware validation, if a rule does not implement `validation.RuleWithContext`, its
|
||||
`validation.Rule` will be used instead.
|
||||
|
||||
|
||||
## Built-in Validation Rules
|
||||
|
||||
The following rules are provided in the `validation` package:
|
||||
|
||||
* `In(...interface{})`: checks if a value can be found in the given list of values.
|
||||
* `NotIn(...interface{})`: checks if a value is NOT among the given list of values.
|
||||
* `Length(min, max int)`: checks if the length of a value is within the specified range.
|
||||
- `In(...interface{})`: checks if a value can be found in the given list of values.
|
||||
- `NotIn(...interface{})`: checks if a value is NOT among the given list of values.
|
||||
- `Length(min, max int)`: checks if the length of a value is within the specified range.
|
||||
This rule should only be used for validating strings, slices, maps, and arrays.
|
||||
* `RuneLength(min, max int)`: checks if the length of a string is within the specified range.
|
||||
- `RuneLength(min, max int)`: checks if the length of a string is within the specified range.
|
||||
This rule is similar as `Length` except that when the value being validated is a string, it checks
|
||||
its rune length instead of byte length.
|
||||
* `Min(min interface{})` and `Max(max interface{})`: checks if a value is within the specified range.
|
||||
- `Min(min interface{})` and `Max(max interface{})`: checks if a value is within the specified range.
|
||||
These two rules should only be used for validating int, uint, float and time.Time types.
|
||||
* `Match(*regexp.Regexp)`: checks if a value matches the specified regular expression.
|
||||
- `Match(*regexp.Regexp)`: checks if a value matches the specified regular expression.
|
||||
This rule should only be used for strings and byte slices.
|
||||
* `Date(layout string)`: checks if a string value is a date whose format is specified by the layout.
|
||||
- `Date(layout string)`: checks if a string value is a date whose format is specified by the layout.
|
||||
By calling `Min()` and/or `Max()`, you can check additionally if the date is within the specified range.
|
||||
* `Required`: checks if a value is not empty (neither nil nor zero).
|
||||
* `NotNil`: checks if a pointer value is not nil. Non-pointer values are considered valid.
|
||||
* `NilOrNotEmpty`: checks if a value is a nil pointer or a non-empty value. This differs from `Required` in that it treats a nil pointer as valid.
|
||||
* `Nil`: checks if a value is a nil pointer.
|
||||
* `Empty`: checks if a value is empty. nil pointers are considered valid.
|
||||
* `Skip`: this is a special rule used to indicate that all rules following it should be skipped (including the nested ones).
|
||||
* `MultipleOf`: checks if the value is a multiple of the specified range.
|
||||
* `Each(rules ...Rule)`: checks the elements within an iterable (map/slice/array) with other rules.
|
||||
* `When(condition, rules ...Rule)`: validates with the specified rules only when the condition is true.
|
||||
* `Else(rules ...Rule)`: must be used with `When(condition, rules ...Rule)`, validates with the specified rules only when the condition is false.
|
||||
- `Required`: checks if a value is not empty (neither nil nor zero).
|
||||
- `NotNil`: checks if a pointer value is not nil. Non-pointer values are considered valid.
|
||||
- `NilOrNotEmpty`: checks if a value is a nil pointer or a non-empty value. This differs from `Required` in that it treats a nil pointer as valid.
|
||||
- `Nil`: checks if a value is a nil pointer.
|
||||
- `Empty`: checks if a value is empty. nil pointers are considered valid.
|
||||
- `Skip`: this is a special rule used to indicate that all rules following it should be skipped (including the nested ones).
|
||||
- `MultipleOf`: checks if the value is a multiple of the specified range.
|
||||
- `Each(rules ...Rule)`: checks the elements within an iterable (map/slice/array) with other rules.
|
||||
- `When(condition, rules ...Rule)`: validates with the specified rules only when the condition is true.
|
||||
- `Else(rules ...Rule)`: must be used with `When(condition, rules ...Rule)`, validates with the specified rules only when the condition is false.
|
||||
|
||||
The `is` sub-package provides a list of commonly used string validation rules that can be used to check if the format
|
||||
of a value satisfies certain requirements. Note that these rules only handle strings and byte slices and if a string
|
||||
or byte slice is empty, it is considered valid. You may use a `Required` rule to ensure a value is not empty.
|
||||
or byte slice is empty, it is considered valid. You may use a `Required` rule to ensure a value is not empty.
|
||||
Below is the whole list of the rules provided by the `is` package:
|
||||
|
||||
* `Email`: validates if a string is an email or not. It also checks if the MX record exists for the email domain.
|
||||
* `EmailFormat`: validates if a string is an email or not. It does NOT check the existence of the MX record.
|
||||
* `URL`: validates if a string is a valid URL
|
||||
* `RequestURL`: validates if a string is a valid request URL
|
||||
* `RequestURI`: validates if a string is a valid request URI
|
||||
* `Alpha`: validates if a string contains English letters only (a-zA-Z)
|
||||
* `Digit`: validates if a string contains digits only (0-9)
|
||||
* `Alphanumeric`: validates if a string contains English letters and digits only (a-zA-Z0-9)
|
||||
* `UTFLetter`: validates if a string contains unicode letters only
|
||||
* `UTFDigit`: validates if a string contains unicode decimal digits only
|
||||
* `UTFLetterNumeric`: validates if a string contains unicode letters and numbers only
|
||||
* `UTFNumeric`: validates if a string contains unicode number characters (category N) only
|
||||
* `LowerCase`: validates if a string contains lower case unicode letters only
|
||||
* `UpperCase`: validates if a string contains upper case unicode letters only
|
||||
* `Hexadecimal`: validates if a string is a valid hexadecimal number
|
||||
* `HexColor`: validates if a string is a valid hexadecimal color code
|
||||
* `RGBColor`: validates if a string is a valid RGB color in the form of rgb(R, G, B)
|
||||
* `Int`: validates if a string is a valid integer number
|
||||
* `Float`: validates if a string is a floating point number
|
||||
* `UUIDv3`: validates if a string is a valid version 3 UUID
|
||||
* `UUIDv4`: validates if a string is a valid version 4 UUID
|
||||
* `UUIDv5`: validates if a string is a valid version 5 UUID
|
||||
* `UUID`: validates if a string is a valid UUID
|
||||
* `CreditCard`: validates if a string is a valid credit card number
|
||||
* `ISBN10`: validates if a string is an ISBN version 10
|
||||
* `ISBN13`: validates if a string is an ISBN version 13
|
||||
* `ISBN`: validates if a string is an ISBN (either version 10 or 13)
|
||||
* `JSON`: validates if a string is in valid JSON format
|
||||
* `ASCII`: validates if a string contains ASCII characters only
|
||||
* `PrintableASCII`: validates if a string contains printable ASCII characters only
|
||||
* `Multibyte`: validates if a string contains multibyte characters
|
||||
* `FullWidth`: validates if a string contains full-width characters
|
||||
* `HalfWidth`: validates if a string contains half-width characters
|
||||
* `VariableWidth`: validates if a string contains both full-width and half-width characters
|
||||
* `Base64`: validates if a string is encoded in Base64
|
||||
* `DataURI`: validates if a string is a valid base64-encoded data URI
|
||||
* `E164`: validates if a string is a valid E164 phone number (+19251232233)
|
||||
* `CountryCode2`: validates if a string is a valid ISO3166 Alpha 2 country code
|
||||
* `CountryCode3`: validates if a string is a valid ISO3166 Alpha 3 country code
|
||||
* `DialString`: validates if a string is a valid dial string that can be passed to Dial()
|
||||
* `MAC`: validates if a string is a MAC address
|
||||
* `IP`: validates if a string is a valid IP address (either version 4 or 6)
|
||||
* `IPv4`: validates if a string is a valid version 4 IP address
|
||||
* `IPv6`: validates if a string is a valid version 6 IP address
|
||||
* `Subdomain`: validates if a string is valid subdomain
|
||||
* `Domain`: validates if a string is valid domain
|
||||
* `DNSName`: validates if a string is valid DNS name
|
||||
* `Host`: validates if a string is a valid IP (both v4 and v6) or a valid DNS name
|
||||
* `Port`: validates if a string is a valid port number
|
||||
* `MongoID`: validates if a string is a valid Mongo ID
|
||||
* `Latitude`: validates if a string is a valid latitude
|
||||
* `Longitude`: validates if a string is a valid longitude
|
||||
* `SSN`: validates if a string is a social security number (SSN)
|
||||
* `Semver`: validates if a string is a valid semantic version
|
||||
- `Email`: validates if a string is an email or not. It also checks if the MX record exists for the email domain.
|
||||
- `EmailFormat`: validates if a string is an email or not. It does NOT check the existence of the MX record.
|
||||
- `URL`: validates if a string is a valid URL
|
||||
- `RequestURL`: validates if a string is a valid request URL
|
||||
- `RequestURI`: validates if a string is a valid request URI
|
||||
- `Alpha`: validates if a string contains English letters only (a-zA-Z)
|
||||
- `Digit`: validates if a string contains digits only (0-9)
|
||||
- `Alphanumeric`: validates if a string contains English letters and digits only (a-zA-Z0-9)
|
||||
- `UTFLetter`: validates if a string contains unicode letters only
|
||||
- `UTFDigit`: validates if a string contains unicode decimal digits only
|
||||
- `UTFLetterNumeric`: validates if a string contains unicode letters and numbers only
|
||||
- `UTFNumeric`: validates if a string contains unicode number characters (category N) only
|
||||
- `LowerCase`: validates if a string contains lower case unicode letters only
|
||||
- `UpperCase`: validates if a string contains upper case unicode letters only
|
||||
- `Hexadecimal`: validates if a string is a valid hexadecimal number
|
||||
- `HexColor`: validates if a string is a valid hexadecimal color code
|
||||
- `RGBColor`: validates if a string is a valid RGB color in the form of rgb(R, G, B)
|
||||
- `Int`: validates if a string is a valid integer number
|
||||
- `Float`: validates if a string is a floating point number
|
||||
- `UUIDv3`: validates if a string is a valid version 3 UUID
|
||||
- `UUIDv4`: validates if a string is a valid version 4 UUID
|
||||
- `UUIDv5`: validates if a string is a valid version 5 UUID
|
||||
- `UUID`: validates if a string is a valid UUID
|
||||
- `ULID`: validates if a string is a valid ULID
|
||||
- `CreditCard`: validates if a string is a valid credit card number
|
||||
- `ISBN10`: validates if a string is an ISBN version 10
|
||||
- `ISBN13`: validates if a string is an ISBN version 13
|
||||
- `ISBN`: validates if a string is an ISBN (either version 10 or 13)
|
||||
- `JSON`: validates if a string is in valid JSON format
|
||||
- `ASCII`: validates if a string contains ASCII characters only
|
||||
- `PrintableASCII`: validates if a string contains printable ASCII characters only
|
||||
- `Multibyte`: validates if a string contains multibyte characters
|
||||
- `FullWidth`: validates if a string contains full-width characters
|
||||
- `HalfWidth`: validates if a string contains half-width characters
|
||||
- `VariableWidth`: validates if a string contains both full-width and half-width characters
|
||||
- `Base64`: validates if a string is encoded in Base64
|
||||
- `DataURI`: validates if a string is a valid base64-encoded data URI
|
||||
- `E164`: validates if a string is a valid E164 phone number (+19251232233)
|
||||
- `CountryCode2`: validates if a string is a valid ISO3166 Alpha 2 country code
|
||||
- `CountryCode3`: validates if a string is a valid ISO3166 Alpha 3 country code
|
||||
- `DialString`: validates if a string is a valid dial string that can be passed to Dial()
|
||||
- `MAC`: validates if a string is a MAC address
|
||||
- `IP`: validates if a string is a valid IP address (either version 4 or 6)
|
||||
- `IPv4`: validates if a string is a valid version 4 IP address
|
||||
- `IPv6`: validates if a string is a valid version 6 IP address
|
||||
- `Subdomain`: validates if a string is valid subdomain
|
||||
- `Domain`: validates if a string is valid domain
|
||||
- `DNSName`: validates if a string is valid DNS name
|
||||
- `Host`: validates if a string is a valid IP (both v4 and v6) or a valid DNS name
|
||||
- `Port`: validates if a string is a valid port number
|
||||
- `MongoID`: validates if a string is a valid Mongo ID
|
||||
- `Latitude`: validates if a string is a valid latitude
|
||||
- `Longitude`: validates if a string is a valid longitude
|
||||
- `SSN`: validates if a string is a social security number (SSN)
|
||||
- `Semver`: validates if a string is a valid semantic version
|
||||
|
||||
## Credits
|
||||
|
||||
@@ -27,7 +27,7 @@ type EachRule struct {
|
||||
|
||||
// Validate loops through the given iterable and calls the Ozzo Validate() method for each value.
|
||||
func (r EachRule) Validate(value interface{}) error {
|
||||
return r.ValidateWithContext(nil, value)
|
||||
return r.ValidateWithContext(context.Background(), value)
|
||||
}
|
||||
|
||||
// ValidateWithContext loops through the given iterable and calls the Ozzo ValidateWithContext() method for each value.
|
||||
@@ -78,10 +78,8 @@ func (r EachRule) getInterface(value reflect.Value) interface{} {
|
||||
if value.IsNil() {
|
||||
return nil
|
||||
}
|
||||
return value.Elem().Interface()
|
||||
default:
|
||||
return value.Interface()
|
||||
}
|
||||
return value.Interface()
|
||||
}
|
||||
|
||||
func (r EachRule) getString(value reflect.Value) string {
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"unicode"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||
"github.com/invopop/validation"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -58,6 +58,8 @@ var (
|
||||
ErrUUIDv5 = validation.NewError("validation_is_uuid_v5", "must be a valid UUID v5")
|
||||
// ErrUUID is the error that returns in case of an invalid UUID value.
|
||||
ErrUUID = validation.NewError("validation_is_uuid", "must be a valid UUID")
|
||||
// ErrULID is the error that returns in case of an invalid ULID value.
|
||||
ErrULID = validation.NewError("validation_is_ulid", "must be a valid ULID")
|
||||
// ErrCreditCard is the error that returns in case of an invalid credit card number.
|
||||
ErrCreditCard = validation.NewError("validation_is_credit_card", "must be a valid credit card number")
|
||||
// ErrISBN10 is the error that returns in case of an invalid ISBN-10 value.
|
||||
@@ -84,7 +86,7 @@ var (
|
||||
ErrBase64 = validation.NewError("validation_is_base64", "must be encoded in Base64")
|
||||
// ErrDataURI is the error that returns in case of an invalid data URI.
|
||||
ErrDataURI = validation.NewError("validation_is_data_uri", "must be a Base64-encoded data URI")
|
||||
// ErrE164 is the error that returns in case of an invalid e165.
|
||||
// ErrE164 is the error that returns in case of an invalid e164.
|
||||
ErrE164 = validation.NewError("validation_is_e164_number", "must be a valid E164 number")
|
||||
// ErrCountryCode2 is the error that returns in case of an invalid two-letter country code.
|
||||
ErrCountryCode2 = validation.NewError("validation_is_country_code_2_letter", "must be a valid two-letter country code")
|
||||
@@ -197,7 +199,7 @@ var (
|
||||
Base64 = validation.NewStringRuleWithError(govalidator.IsBase64, ErrBase64)
|
||||
// DataURI validates if a string is a valid base64-encoded data URI
|
||||
DataURI = validation.NewStringRuleWithError(govalidator.IsDataURI, ErrDataURI)
|
||||
// E164 validates if a string is a valid ISO3166 Alpha 2 country code
|
||||
// E164 validates if a string is a valid E164 telephone number
|
||||
E164 = validation.NewStringRuleWithError(isE164Number, ErrE164)
|
||||
// CountryCode2 validates if a string is a valid ISO3166 Alpha 2 country code
|
||||
CountryCode2 = validation.NewStringRuleWithError(govalidator.IsISO3166Alpha2, ErrCountryCode2)
|
||||
@@ -275,7 +277,7 @@ func isDomain(value string) bool {
|
||||
|
||||
func isUTFNumeric(value string) bool {
|
||||
for _, c := range value {
|
||||
if unicode.IsNumber(c) == false {
|
||||
if !unicode.IsNumber(c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -41,10 +41,11 @@ type (
|
||||
// Use Key() to specify map keys that need to be validated. Each Key() call specifies a single key which can
|
||||
// be associated with multiple rules.
|
||||
// For example,
|
||||
// validation.Map(
|
||||
// validation.Key("Name", validation.Required),
|
||||
// validation.Key("Value", validation.Required, validation.Length(5, 10)),
|
||||
// )
|
||||
//
|
||||
// validation.Map(
|
||||
// validation.Key("Name", validation.Required),
|
||||
// validation.Key("Value", validation.Required, validation.Length(5, 10)),
|
||||
// )
|
||||
//
|
||||
// A nil value is considered valid. Use the Required rule to make sure a map value is present.
|
||||
func Map(keys ...*KeyRules) MapRule {
|
||||
@@ -59,7 +60,7 @@ func (r MapRule) AllowExtraKeys() MapRule {
|
||||
|
||||
// Validate checks if the given value is valid or not.
|
||||
func (r MapRule) Validate(m interface{}) error {
|
||||
return r.ValidateWithContext(nil, m)
|
||||
return r.ValidateWithContext(context.Background(), m)
|
||||
}
|
||||
|
||||
// ValidateWithContext checks if the given value is valid or not.
|
||||
@@ -47,20 +47,20 @@ func (e ErrFieldNotFound) Error() string {
|
||||
// should be specified as a pointer to the field. A field can be associated with multiple rules.
|
||||
// For example,
|
||||
//
|
||||
// value := struct {
|
||||
// Name string
|
||||
// Value string
|
||||
// }{"name", "demo"}
|
||||
// err := validation.ValidateStruct(&value,
|
||||
// validation.Field(&a.Name, validation.Required),
|
||||
// validation.Field(&a.Value, validation.Required, validation.Length(5, 10)),
|
||||
// )
|
||||
// fmt.Println(err)
|
||||
// // Value: the length must be between 5 and 10.
|
||||
// value := struct {
|
||||
// Name string
|
||||
// Value string
|
||||
// }{"name", "demo"}
|
||||
// err := validation.ValidateStruct(&value,
|
||||
// validation.Field(&a.Name, validation.Required),
|
||||
// validation.Field(&a.Value, validation.Required, validation.Length(5, 10)),
|
||||
// )
|
||||
// fmt.Println(err)
|
||||
// // Value: the length must be between 5 and 10.
|
||||
//
|
||||
// An error will be returned if validation fails.
|
||||
func ValidateStruct(structPtr interface{}, fields ...*FieldRules) error {
|
||||
return ValidateStructWithContext(nil, structPtr, fields...)
|
||||
return ValidateStructWithContext(context.Background(), structPtr, fields...)
|
||||
}
|
||||
|
||||
// ValidateStructWithContext validates a struct with the given context.
|
||||
@@ -20,7 +20,7 @@ type WhenRule struct {
|
||||
|
||||
// Validate checks if the condition is true and if so, it validates the value using the specified rules.
|
||||
func (r WhenRule) Validate(value interface{}) error {
|
||||
return r.ValidateWithContext(nil, value)
|
||||
return r.ValidateWithContext(context.Background(), value)
|
||||
}
|
||||
|
||||
// ValidateWithContext checks if the condition is true and if so, it validates the value using the specified rules.
|
||||
@@ -28,16 +28,14 @@ func (r WhenRule) ValidateWithContext(ctx context.Context, value interface{}) er
|
||||
if r.condition {
|
||||
if ctx == nil {
|
||||
return Validate(value, r.rules...)
|
||||
} else {
|
||||
return ValidateWithContext(ctx, value, r.rules...)
|
||||
}
|
||||
return ValidateWithContext(ctx, value, r.rules...)
|
||||
}
|
||||
|
||||
if ctx == nil {
|
||||
return Validate(value, r.elseRules...)
|
||||
} else {
|
||||
return ValidateWithContext(ctx, value, r.elseRules...)
|
||||
}
|
||||
return ValidateWithContext(ctx, value, r.elseRules...)
|
||||
}
|
||||
|
||||
// Else returns a validation rule that executes the given list of rules when the condition is false.
|
||||
8
vendor/modules.txt
vendored
8
vendor/modules.txt
vendored
@@ -981,10 +981,6 @@ github.com/go-micro/plugins/v4/wrapper/monitoring/prometheus
|
||||
# github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry v1.2.0
|
||||
## explicit; go 1.17
|
||||
github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry
|
||||
# github.com/go-ozzo/ozzo-validation/v4 v4.3.0
|
||||
## explicit; go 1.13
|
||||
github.com/go-ozzo/ozzo-validation/v4
|
||||
github.com/go-ozzo/ozzo-validation/v4/is
|
||||
# github.com/go-playground/locales v0.14.1
|
||||
## explicit; go 1.17
|
||||
github.com/go-playground/locales
|
||||
@@ -1224,6 +1220,10 @@ github.com/imdario/mergo
|
||||
# github.com/inconshreveable/mousetrap v1.1.0
|
||||
## explicit; go 1.18
|
||||
github.com/inconshreveable/mousetrap
|
||||
# github.com/invopop/validation v0.3.0
|
||||
## explicit; go 1.16
|
||||
github.com/invopop/validation
|
||||
github.com/invopop/validation/is
|
||||
# github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
|
||||
## explicit
|
||||
github.com/jbenet/go-context/io
|
||||
|
||||
Reference in New Issue
Block a user