github.com/System-Glitch/goyave/v2@v2.10.3-0.20200819142921-51011e75d504/docs_src/src/guide/basics/validation.md (about)

     1  ---
     2  meta:
     3    - name: "og:title"
     4      content: "Validation - Goyave"
     5    - name: "twitter:title"
     6      content: "Validation - Goyave"
     7    - name: "title"
     8      content: "Validation - Goyave"
     9  ---
    10  
    11  # Validation
    12  
    13  [[toc]]
    14  
    15  ## Introduction
    16  
    17  Goyave provides a powerful, yet easy way to validate all incoming data, no matter its type or its format, thanks to a large number of validation rules.
    18  
    19  Incoming requests are validated using **rules set**, which associate rules with each expected field in the request.
    20  
    21  Validation rules can **alter the raw data**. That means that when you validate a field to be number, if the validation passes, you are ensured that the data you'll be using in your controller handler is a `float64`. Or if you're validating an IP, you get a `net.IP` object.
    22  
    23  If a request contains a field with a `nil`/`null` value, and that this field doesn't have the `nullable` rule, the field is **removed** entirely from the request.
    24  
    25  Validation is automatic. You just have to define a rules set and assign it to a route. When the validation doesn't pass, the request is stopped and the validation errors messages are sent as a response, using the correct [language](../advanced/localization.html). The HTTP response code of failed validation is **422 "Unprocessable Entity"**, or **400 "Bad Request"** if the body could not be parsed.
    26  
    27  ::: tip
    28  You can customize the validation error messages by editing `resources/lang/<language>/rules.json`. Learn more in the [localization](../advanced/localization.html) section.
    29  :::
    30  
    31  The following features require the `validation` package to be imported.
    32  
    33  ``` go
    34  import "github.com/System-Glitch/goyave/v2/validation"
    35  ```
    36  
    37  ## Rules sets
    38  
    39  Rule sets are defined in the same package as the controller, typically in a separate file named `request.go`. Rule sets are named after the name of the controller handler they will be used with, and end with `Request`. For example, a rule set for the `Store` handler will be named `StoreRequest`. If a rule set can be used for multiple handlers, consider using a name suited for all of them. The rules for a store operation are often the same for update operations, so instead of duplicating the set, create one unique set called `UpsertRequest`.
    40  
    41  **Example:** (`http/controller/product/request.go`)
    42  ``` go
    43  var (
    44  	StoreRequest validation.RuleSet = validation.RuleSet{
    45  		"name":  {"required", "string", "between:3,50"},
    46  		"price": {"required", "numeric", "min:0.01"},
    47  		"image": {"nullable", "file", "image", "max:2048", "count:1"},
    48      }
    49      
    50      // ...
    51  )
    52  ```
    53  
    54  ::: warning
    55  **The order in which you assign rules is important**, as rules are executed in this order. The rules checking for the type of the data should **always be first**, or after `required` and `nullable`.
    56  
    57  If a field is not **required** and is missing from the request, **no rules are checked**!
    58  :::
    59  
    60  ::: tip
    61  `validation.RuleSet` is an alias for `map[string][]string`.
    62  :::
    63  
    64  ---
    65  
    66  Once your rules sets are defined, you need to assign them to your routes using the `Validate()` method. Learn more about routing in the [dedicated section](./routing.html).
    67  
    68  ``` go
    69  router.Post("/product", product.Store).Validate(product.StoreRequest)
    70  ```
    71  
    72  ## Available validation rules
    73  
    74  ::: table
    75  [Required](#required)
    76  [Nullable](#nullable)
    77  [Numeric](#numeric)
    78  [Integer](#integer)
    79  [Min](#min-value)
    80  [Max](#max-value)
    81  [Between](#between-min-max)
    82  [Greater than](#greater-than-field)
    83  [Greater than or equal](#greater-than-equal-field)
    84  [Lower than](#lower-than-field)
    85  [Lower than or equal](#lower-than-equal-field)
    86  [String](#string)
    87  [Array](#array-type)
    88  [Distinct](#distinct)
    89  [Digits](#digits)
    90  [Regex](#regex-pattern)
    91  [Email](#email)
    92  [Size](#size-value)
    93  [Alpha](#alpha)
    94  [Alpha dash](#alpha-dash)
    95  [Alpha numeric](#alpha-num)
    96  [Starts with](#starts-with-value1)
    97  [Ends with](#ends-with-value1)
    98  [In](#in-value1-value2)
    99  [Not in](#not-in-value1-value2)
   100  [In array](#in-array-field)
   101  [Not in array](#not-in-array-field)
   102  [Timezone](#timezone)
   103  [IP](#ip)
   104  [IPv4](#ipv4)
   105  [IPv6](#ipv6)
   106  [JSON](#json)
   107  [URL](#url)
   108  [UUID](#uuid-version)
   109  [Bool](#bool)
   110  [Same](#same-field)
   111  [Different](#different-field)
   112  [Confirmed](#confirmed)
   113  [File](#file)
   114  [MIME](#mime-foo)
   115  [Image](#image)
   116  [Extension](#extension-foo)
   117  [Count](#count-value)
   118  [Count min](#count-min-value)
   119  [Count max](#count-max-value)
   120  [Count between](#count-between-min-max)
   121  [Date](#date-format)
   122  [Before](#before-date)
   123  [Before or equal](#before-equal-date)
   124  [After](#after-date)
   125  [After or equal](#after-equal-date)
   126  [Date equals](#date-equals-date)
   127  [Date between](#date-between-date1-date2)
   128  :::
   129  
   130  #### required
   131  
   132  The field under validation must be present.
   133  
   134  If the field is a string, the string must not be empty. If a field is `null` and has the `nullable` rule, the `required` rules passes. As non-nullable fields are removed if they have a `null` value, the `required` rule doesn't pass if a field is `null` and doesn't have the `nullable` rule.
   135  
   136  #### nullable
   137  
   138  The field under validation can have a `nil`/`null` value. If this rule is missing from the rules set, the field will be **removed** if it is `null`. This rule is especially useful when working with JSON requests or with primitives that can contain null values.
   139  
   140  Be sure to check if your field is not null before using it in your handlers.
   141  ``` go
   142  // In this example, field is numeric
   143  if val, exists := request.Data["field"]; exists && val != nil {
   144      field, _ := request.Data["field"].(float64)
   145  }
   146  ```
   147  
   148  #### numeric
   149  
   150  The field under validation must be numeric. Strings that can be converted to numbers are accepted.
   151  This rule converts the field to `float64` if it passes.
   152  
   153  #### integer
   154  
   155  The field under validation must be an integer. Strings that can be converted to an integer are accepted.
   156  This rule converts the field to `int` if it passes.
   157  
   158  #### min:value
   159  
   160  Depending on its type, the field under validation must be at least `value`.
   161  Strings, numerics, array, and files are evaluated using the same method as the [`size`](#size-value) rule.
   162  
   163  #### max:value
   164  
   165  Depending on its type, the field under validation must not be superior to `value`.
   166  Strings, numerics, array, and files are evaluated using the same method as the [`size`](#size-value) rule.
   167  
   168  #### between:min,max
   169  
   170  Depending on its type, the field under validation must be between `min` and `max`.
   171  Strings, numerics, array, and files are evaluated using the same method as the [`size`](#size-value) rule.
   172  
   173  #### greater_than:field
   174  
   175  The field under validation must be greater than the given `field`. The two fields must have the same type.
   176  Strings, numerics, array, and files are evaluated using the same method as the [`size`](#size-value) rule.
   177  
   178  #### greater_than_equal:field
   179  
   180  The field under validation must be greater or equal to the given `field`. The two fields must have the same type.
   181  Strings, numerics, array, and files are evaluated using the same method as the [`size`](#size-value) rule.
   182  
   183  #### lower_than:field
   184  
   185  The field under validation must be lower than the given `field`. The two fields must have the same type.
   186  Strings, numerics, array, and files are evaluated using the same method as the [`size`](#size-value) rule.
   187  
   188  #### lower_than_equal:field
   189  
   190  The field under validation must be lower or equal to the given `field`. The two fields must have the same type.
   191  Strings, numerics, array, and files are evaluated using the same method as the [`size`](#size-value) rule.
   192  
   193  #### string
   194  
   195  The field under validation must be a string.
   196  
   197  #### array:type
   198  
   199  The field under validation must be an array. The `type` parameter is **optional**.
   200  
   201  If no type is provided, the field has the type `[]interface{}` after validation. If a type is provided, the array is converted to a slice of the correct type, and all values in the array are validated in the same way as standard fields.
   202  
   203  For example, with the rule `array:url`, all values must be valid URLs and the field will be converted to `[]*url.URL`.
   204  
   205  **Available types:**
   206  - `string`
   207  - `numeric`
   208  - `integer`
   209  - `timezone`
   210  - `ip`, `ipv4`, `ipv6`
   211  - `url`
   212  - `uuid`
   213  - `bool`
   214  - `date`
   215  
   216  ::: tip
   217  For the `uuid` and `date` types, you can pass a second parameter: `array:date,02-01-2006`
   218  :::
   219  
   220  #### distinct
   221  
   222  The field under validation must be an array and have distinct values.
   223  
   224  #### digits
   225  
   226  The field under validation must be a string and contain only digits.
   227  
   228  #### regex:pattern
   229  
   230  The field under validation must be a string and match the given `pattern`.
   231  
   232  #### email
   233  
   234  The field under validation must be a string and be an email address.
   235  
   236  ::: warning
   237  This rule is not enough to properly validate email addresses. The only way to ensure an email address is valid is by sending a confirmation email.
   238  :::
   239  
   240  #### size:value
   241  
   242  Depending on its type, the field under validation must:
   243  - Strings: have a length of `value` characters.
   244  - Numerics: be equal to `value`.
   245  - Arrays: exactly have `value` items.
   246  - Files: weight exactly `value` KiB. 
   247      - *Note: for this rule only (not for `min`, `max`, etc), the size of the file under validation is **rounded** to the closest KiB.*
   248      - When the field is a multi-files upload, the size of **all files** is checked.
   249  
   250  ::: warning
   251  If the value cannot be validated because its type is unsupported, the rule passes. Therefore, you should always validate the type of the field **before** using the `size`, `min`, `lower_than`, ... rules.
   252  :::
   253  
   254  #### alpha
   255  
   256  The field under validation must be a string and be entirely alphabetic characters.
   257  
   258  #### alpha_dash
   259  
   260  The field under validation must be a string and be entirely alphabetic-numeric characters, dashes or underscores.
   261  
   262  #### alpha_num
   263  
   264  The field under validation must be a string and be entirely alphabetic-numeric characters.
   265  
   266  #### starts_with:value1,...
   267  
   268  The field under validation must be a string and start with of the given values.
   269  
   270  #### ends_with:value1,...
   271  
   272  The field under validation must be a string and end with one of the given values.
   273  
   274  #### in:value1,value2,...
   275  
   276  The field under validation must be a one of the given values. Only numerics and strings are checked.
   277  
   278  #### not_in:value1,value2,...
   279  
   280  The field under validation must not be a one of the given values. Only numerics and strings are checked.
   281  
   282  #### in_array:field
   283  
   284  The field under validation must be a one of the values in the given `field`. Only numerics and strings are checked, and the given `field` must be an array.
   285  
   286  #### not_in_array:field
   287  
   288  The field under validation must not be a one of the values in the given `field`. Only numerics and strings are checked, and the given `field` must be an array.
   289  
   290  #### timezone
   291  
   292  The field under validation must be a string and be a valid timezone. This rule converts the field to `*time.Location` if it passes.
   293  
   294  Valid timezones are:
   295  - UTC
   296  - Timezones from the IANA Time Zone database, such as `America/New_York`
   297  
   298  The time zone database needed by LoadLocation may not be present on all systems, especially non-Unix systems. The rules looks in the directory or uncompressed zip file
   299  named by the `ZONEINFO` environment variable, if any, then looks in known installation locations on Unix systems, and finally looks in `$GOROOT/lib/time/zoneinfo.zip`.
   300  
   301  #### ip
   302  
   303  The field under validation must be a string and be either an IPv4 address or an IPv6 address.
   304  This rule converts the field to `net.IP` if it passes.
   305  
   306  #### ipv4
   307  
   308  The field under validation must be a string and be an IPv4 address.
   309  This rule converts the field to `net.IP` if it passes.
   310  
   311  #### ipv6
   312  
   313  The field under validation must be a string and be an IPv6 address.
   314  This rule converts the field to `net.IP` if it passes.
   315  
   316  #### json
   317  
   318  The field under validation must be a valid JSON string. This rule unmarshals the string and sets the field value to the unmarshalled result.
   319  
   320  #### url
   321  
   322  The field under validation must be a valid URL.
   323  This rule converts the field to `*url.URL` if it passes.
   324  
   325  #### uuid:version
   326  
   327  The field under validation must be a string and a valid UUID.
   328  
   329  The `version` parameter is **optional**.
   330  - If a `version` is given (`uuid:3`,`uuid:4`,`uuid:5`), the rule will pass only if the version of the UUID matches.  
   331  - If no `version` is given, any UUID version is accepted.
   332  
   333  This rule converts the field to `uuid.UUID` if it passes.
   334  
   335  #### bool
   336  
   337  The field under validation must be a boolean or one of the following values:
   338  - `1`/`0`
   339  - `"1"`/`"0"`
   340  - `"on"`/`"off"`
   341  - `"true"`/`"false"`
   342  - `"yes"`/`"no"`
   343  
   344  This rule converts the field to `bool` if it passes.
   345  
   346  #### same:field
   347  
   348  The field under validation must have the same value as the given `field`. For arrays, the two fields must have the same values in the same order.
   349  
   350  The two fields must have the same type. Files are not checked.
   351  
   352  #### different:field
   353  
   354  The field under validation must have a different value from the given `field`. For arrays, the two fields must have different values or not be in the same order.
   355  
   356  The two fields must have the same type. Files are not checked.
   357  
   358  #### confirmed
   359  
   360  The field under validation must have a matching `foo_confirmation`. This rule validate equality in the same way as the [`same`](#same-field) rule.
   361  
   362  For example, if the field under validation is `password`, a matching `password_confirmation` field must be present in the input.
   363  
   364  #### file
   365  
   366  The field under validation must be a file. Multi-files are supported.
   367  This rule converts the field to `[]filesystem.File` if it passes.
   368  
   369  #### mime:foo,...
   370  
   371  The field under validation must be a file and match one of the given MIME types. If the field is a multi-files, all files must satisfy this rule.
   372  
   373  #### image
   374  
   375  The field under validation must be a file and match one of the following MIME types:
   376  - `image/jpeg`
   377  - `image/png`
   378  - `image/gif`
   379  - `image/bmp`
   380  - `image/svg+xml`
   381  - `image/webp`
   382  
   383  If the field is a multi-files, all files must satisfy this rule.
   384  
   385  #### extension:foo,...
   386  
   387  The field under validation must be a file and match one of the given extensions. If the field is a multi-files, all files must satisfy this rule.
   388  
   389  #### count:value
   390  
   391  The field under validation must be a multi-file and contain `value` files.
   392  
   393  #### count_min:value
   394  
   395  The field under validation must be a multi-file and contain at least `value` files.
   396  
   397  #### count_max:value
   398  
   399  The field under validation must be a multi-file and may not contain more than `value` files.
   400  
   401  #### count_between:min,max
   402  
   403  The field under validation must be a multi-file and contain between `min` and `max` files.
   404  
   405  #### date:format
   406  
   407  The field under validation must be a string representing a date. The `format` is optional. If no format is given, the `2006-01-02` format is used.
   408  
   409  This rule converts the field to `time.Time` if it passes.
   410  
   411  ::: tip
   412  See the [Golang datetime format](https://golang.org/src/time/format.go).
   413  :::
   414  
   415  ::: warning
   416  When validating dates by comparing them together, the order of the declaration of the fields in the request is important. For example, if you want to validate that an end date is after a start date, the start date should be declared **before** the end date in the rules set.
   417  
   418  If a date has not been validated and converted yet, the date comparison rules will attempt to parse the dates using the following format: `2006-01-02`.
   419  :::
   420  
   421  #### before:date
   422  
   423  The field under validation must be a value preceding the given date. The `date` must be written using following format: `2006-01-02T15:04:05`.
   424  
   425  If the name of another field is given as a `date`, then the two fields must be a date and the field under validation must be preceding the given field.
   426  
   427  #### before_equal:date
   428  
   429  The field under validation must be a value preceding or equal to the given date. The `date` must be written using following format: `2006-01-02T15:04:05`.
   430  
   431  If the name of another field is given as a `date`, then the two fields must be a date and the field under validation must be preceding or equal to given field.
   432  
   433  #### after:date
   434  
   435  The field under validation must be a value after the given date. The `date` must be written using following format: `2006-01-02T15:04:05`.
   436  
   437  If the name of another field is given as a `date`, then the two fields must be a date and the field under validation must be preceding the given field.
   438  
   439  #### after_equal:date
   440  
   441  The field under validation must be a value after or equal to the given date. The `date` must be written using following format: `2006-01-02T15:04:05`.
   442  
   443  If the name of another field is given as a `date`, then the two fields must be a date and the field under validation must be after or equal to given field.
   444  
   445  #### date_equals:date
   446  
   447  The field under validation must be a value equal to the given date. The `date` must be written using following format: `2006-01-02T15:04:05`.
   448  
   449  If the name of another field is given as a `date`, then the two fields must be a date and the field under validation must be equal to given field.
   450  
   451  #### date_between:date1,date2
   452  
   453  The field under validation must be a value between or equal to the given dates. The given dates must be written using following format: `2006-01-02T15:04:05`.
   454  
   455  If the name of another field is given as a date, then all the fields must be a date and the field under validation must be between or equal to given fields.
   456  
   457  ## Custom rules
   458  
   459  If none of the available validation rules satisfy your needs, you can implement custom validation rules. To do so, create a new file `http/validation/validation.go` in which you are going to define your custom rules.
   460  
   461  Rules definition shouldn't be exported, and start with `validate`. A rule returns a `bool`, indicating if the validation passed or not.
   462  
   463  ``` go
   464  func validateCustomFormat(field string, value interface{}, parameters []string, form map[string]interface{}) bool {
   465      str, ok := value.(string)
   466  
   467      if ok { // The data under validation is a string
   468          return regexp.MustCompile(parameters[0]).MatchString(str)
   469      }
   470  
   471      return false // Cannot validate this field
   472  }
   473  ```
   474  ::: tip
   475  - `validation.RuleFunc` is an alias for `func(string, interface{}, []string, map[string]interface{}) bool`
   476  - The `form` parameter lets you access the whole form data, and modify it if needed.
   477  - The custom rule in the example above validates a string using a regex. If you need this kind of validation, prefer the included `regex` validation rule.
   478  :::
   479  
   480  Now that your rule behavior is defined, you need to **register** your rule. Do this in an `init()` function in your `validation.go` file.
   481  
   482  #### validation.AddRule
   483  
   484  Register a validation rule.
   485  
   486  The rule will be usable in request validation by using the given rule name.
   487  
   488  Type-dependent messages let you define a different message for numeric, string, arrays and files. The language entry used will be "validation.rules.rulename.type"
   489  
   490  | Parameters                        | Return |
   491  |-----------------------------------|--------|
   492  | `name string`                     | `void` |
   493  | `rule *validation.RuleDefinition` |        |
   494  
   495  **Example:**
   496  ``` go
   497  func init() {
   498      validation.AddRule("custom_format", &validation.RuleDefinition{
   499          Function:           validateCustomFormat,
   500          RequiredParameters: 1, // Ensure the rule has at least one parameter
   501  	})
   502  }
   503  ```
   504  
   505  The **RuleDefinition** struct is defined as follows:
   506  
   507  ```go
   508  type RuleDefinition struct {
   509  
   510  	// The Function field is the function that will be executed
   511  	Function RuleFunc
   512  
   513  	// The minimum amount of parameters
   514  	RequiredParameters int
   515  
   516  	// A type rule is a rule that checks if a field has a certain type
   517  	// and can convert the raw value to a value fitting. For example, the UUID
   518  	// rule is a type rule because it takes a string as input, checks if it's a
   519  	// valid UUID and converts it to a "uuid.UUID".
   520  	IsType bool
   521  
   522  	// Type-dependent rules are rules that can be used with different field types
   523      // (numeric, string, arrays and files) and have a different validation messages
   524      // depending on the type.
   525  	// The language entry used will be "validation.rules.rulename.type"
   526  	IsTypeDependent bool
   527  }
   528  ```
   529  
   530  ### Adding a message to your rule
   531  
   532  Finally, you may want to add a custom validation message for your rule so the client knows what's wrong with its request. Open `resources/lang/en-US/rules.json` and add an entry with the name of your rule as key:
   533  
   534  ```json
   535  {
   536      //...
   537      "custom_format": "The :field format is invalid.",
   538  }
   539  ```
   540  
   541  If you are supporting multiple languages, don't forget to add this to your other `rules.json` files too.
   542  
   543  ::: tip
   544  Learn more about validation rules messages in the [Localization documentation](../advanced/localization.html#rules).
   545  :::
   546  
   547  #### validation.GetFieldType
   548  
   549  <p><Badge text="Since v2.0.0"/></p>
   550  
   551  returns the non-technical type of the given `value` interface.
   552  This is used by validation rules to know if the input data is a candidate
   553  for validation or not and is especially useful for type-dependent rules.
   554  - `numeric` if the value is an int, uint or a float
   555  - `string` if the value is a string
   556  - `array` if the value is a slice
   557  - `file` if the value is a slice of `filesystem.File`
   558  - `unsupported` otherwise
   559  
   560  | Parameters          | Return   |
   561  |---------------------|----------|
   562  | `value interface{}` | `string` |
   563  
   564  **Example:**
   565  ``` go
   566  validation.GetFieldType("foo") // "string"
   567  validation.GetFieldType(2) // "numeric"
   568  validation.GetFieldType(2.4) // "numeric"
   569  validation.GetFieldType([]int{1,2}) // "array"
   570  ```
   571  
   572  ## Validating arrays
   573  
   574  <p><Badge text="Since v2.1.0"/></p>
   575  
   576  Validating arrays is easy. All the validation rules, **except the file-related rules and the `confirmed` rule**, can be applied to array values using the prefix `>`. When array values are validated, **all of them** must pass the validation.
   577  
   578  **Example:**
   579  ``` go
   580  var arrayValidation = validation.RuleSet{
   581      "array": {"required", "array:string", "between:1,5", ">email", ">max:128"},
   582  }
   583  ```
   584  In this example, we are validating an array of one to five email addresses, which can't be longer than 128 characters.
   585  
   586  ### N-dimensional arrays
   587  
   588  You can validate n-dimensional arrays. 
   589  
   590  **Example:**
   591  ``` go
   592  var arrayValidation = RuleSet{
   593      "array": {"required", "array", ">array", ">>array:numeric", ">max:3", ">>>max:4"},
   594  }
   595  ```
   596  In this example, we are validating a three-dimensional array of numeric values. The second dimension must be made of arrays with a size of 3 or less. The third dimension must contain numbers inferior or equal to 4. The following JSON input passes the validation:
   597  ```json
   598  {
   599      "array": [
   600          [[0.5, 1.42], [0.6, 4, 3]],
   601          [[0.6, 1.43], [], [2]]
   602      ]
   603  }
   604  ```
   605  
   606  ## Placeholders
   607  
   608  Validation messages can use placeholders to inject dynamic values in the validation error message. For example, in the `rules.json` language file:
   609  
   610  ```json
   611  "between.string": "The :field must be between :min and :max characters."
   612  ```
   613  
   614  Here, the `:field` placeholder will be replaced by the field name, `:min`  with the first parameter and `:max` with the second parameter, effectively giving the following result:
   615  
   616  ```
   617  The password must be between 6 and 32 characters. 
   618  ```
   619  
   620  Placeholders are **replacer functions**. In fact, `validation.Placeholder` is an alias for `func(string, string, []string, string) string`. These functions should return the value to replace the placeholder with.
   621  
   622  **Example:**
   623  ``` go
   624  func simpleParameterPlaceholder(field string, rule string, parameters []string, language string) string {
   625  	return parameters[0]
   626  }
   627  ```
   628  
   629  ---
   630  
   631  Placeholders are implemented in the `http/validation/placeholder.go`. To register a custom placeholder, use the `validation.SetPlaceholder()` function, preferably in the `init()` function of your `placeholder.go` file.
   632  
   633  #### validation.SetPlaceholder
   634  
   635  Sets the replacer function for the given placeholder. Don't include the colon prefix in the placeholder name.
   636  
   637  If a placeholder with this name already exists, the latter will be overridden.
   638  
   639  
   640  | Parameters                        | Return |
   641  |-----------------------------------|--------|
   642  | `placeholderName string`          | `void` |
   643  | `replacer validation.Placeholder` |        |
   644  
   645  **Example:**
   646  ``` go
   647  validation.SetPlaceholder("min", func(field string, rule string, parameters []string, language string) string {
   648    	return parameters[0] // Replace ":min" by the first parameter in the rule definition
   649  })
   650  ```
   651  
   652  ### Available placeholders
   653  
   654  #### :field
   655  
   656  `:field` is replaced by the name of the field. If it exists, the replacer with favor the language lines in `fields.json`.
   657  
   658  #### :other
   659  
   660  `:other` is replaced by the name of the field given as first parameter in the rule definition. If it exists, the replacer with favor the language lines in `fields.json`.
   661  
   662  For example, the `same:password_confirmation` rule compares two fields together and returns the following message if the validation fails: 
   663  ```
   664  The :field and the :other must match.
   665  
   666  The password and the password confirmation must match.
   667  ```
   668  
   669  #### :value
   670  
   671  `:value` is replaced by the first parameter of the rule definition.
   672  
   673  #### :values
   674  
   675  `:values` is replaced by a concatenation of all rule parameters, joined by a comma.
   676  
   677  #### :min
   678  
   679  `:min` is replaced by the first parameter of the rule definition.
   680  
   681  #### :max
   682  
   683  `:max` is replaced by the first parameter of the rule definition, or the second if the rule name contains `between`.
   684  
   685  #### :version
   686  
   687  `:version` is replaced by a concatenation of `v` and the first parameter of the rule definition, or by an empty string if the rule doesn't have any parameter.
   688  
   689  For example, for the `UUID:4` rule, the result would be `v4`.
   690  
   691  #### :date
   692  
   693  `:date` is replaced by the first parameter of the rule definition. If the first parameter is a field name, `:date` will be replaced with the name of the field in the same way as the `:other` placeholder.
   694  
   695  #### :max_date
   696  
   697  `:max_date` is replaced by the second parameter of the rule definition. If the second parameter is a field name, `:max_date` will be replaced with the name of the field in the same way as the `:other` placeholder.
   698  
   699  ## Manual validation
   700  
   701  <p><Badge text="Since v2.1.0"/></p>
   702  
   703  You may need to validate some data manually as part of your business logic. You can use the Goyave validator to do so.
   704  
   705  #### validation.Validate
   706  
   707  Validate the given data with the given rule set. If all validation rules pass, returns an empty `validation.Errors`.
   708  
   709  The third parameter (`isJSON`) tells the function if the data comes from a JSON request. This is used to return the correct message if the given data is `nil` and to correctly handle arrays in url-encoded requests.
   710  
   711  The last parameter (`language`) sets the language of the validation error messages.
   712  
   713  | Parameters                    | Return              |
   714  |-------------------------------|---------------------|
   715  | `data map[string]interface{}` | `validation.Errors` |
   716  | `rules validation.Ruler`      |                     |
   717  | `isJSON bool`                 |                     |
   718  | `language string`             |                     |
   719  
   720  ::: tip
   721  - `validation.Errors` is an alias for `map[string][]string`. The key represents the field name and the associated slice contains all already translated validation error messages for this field.
   722  - `validation.Ruler` is an interface that both `validation.RuleSet` and `validation.Rules` implement.
   723  :::
   724  
   725  **Example:**
   726  ``` go
   727  func Store(response *goyave.Response, request *goyave.Request) {
   728      data := map[string]interface{}{
   729  		"string": "hello world",
   730  		"number": 42,
   731  	}
   732  
   733  	errors := validation.Validate(data, validation.RuleSet{
   734  		"string": {"required", "string"},
   735  		"number": {"required", "numeric", "min:10"},
   736  	}, true, request.Lang)
   737  
   738  	if len(errors) > 0 {
   739  		response.JSON(http.StatusUnprocessableEntity, map[string]validation.Errors{"validationError": errors})
   740  		return
   741  	}
   742  
   743  	// data can be safely used from here
   744  	// ...
   745  }
   746  ```
   747  
   748  ## Alternative syntax
   749  
   750  <p><Badge text="Since v3.0.0"/></p>
   751  
   752  Internally, `validation.RuleSet` is parsed and replaced with a more complex structure the first time it is used: `validation.Rules`. This avoids having to parse rules everytime a request is received. Both `validation.RuleSet` and `validation.Rules` can be used when calling `validation.Validate()`, as they both implement the `validation.Ruler` interface. The syntax for `validation.Rules` is significantly more verbose and harder to read,
   753  
   754  Here is an example of rule definition using `validation.Rules` instead of `validation.RuleSet`:
   755  
   756  ```go
   757  rules := &validation.Rules{
   758      Fields: validation.FieldMap{
   759          "email": {
   760              Rules: []*validation.Rule{
   761                  {Name: "required"},
   762                  {Name: "string"},
   763                  {Name: "between", Params: []string{"3", "125"}},
   764                  {Name: "email"},
   765              },
   766          },
   767          "password": {
   768              Rules: []*validation.Rule{
   769                  {Name: "required"},
   770                  {Name: "string"},
   771                  {Name: "between", Params: []string{"6", "64"}},
   772                  {Name: "confirmed"},
   773              },
   774          },
   775          "info": {
   776              Rules: []*validation.Rule{
   777                  {Name: "nullable"},
   778                  {Name: "array", Params: []string{"string"}},
   779                  {Name: "min", Params: []string{"2"}, ArrayDimension: 1},
   780              },
   781          },
   782      },
   783  }
   784  
   785  // Is the same as:
   786  set := validation.RuleSet{
   787      "email":    {"required", "string", "between:3,125", "email"},
   788      "password": {"required", "string", "between:6,64", "confirmed"},
   789      "info":     {"nullable", "array:string", ">min:2"},
   790  }
   791  ```
   792  
   793  ::: tip
   794  - `validation.FieldMap` is an alias for `map[string]*validation.Field`
   795  - You can use this syntax if you need commas to be part of the values of a rule parameters.
   796  :::