README.md
1govalidator
2===========
3[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/asaskevich/govalidator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![GoDoc](https://godoc.org/github.com/asaskevich/govalidator?status.png)](https://godoc.org/github.com/asaskevich/govalidator)
4[![Build Status](https://travis-ci.org/asaskevich/govalidator.svg?branch=master)](https://travis-ci.org/asaskevich/govalidator)
5[![Coverage](https://codecov.io/gh/asaskevich/govalidator/branch/master/graph/badge.svg)](https://codecov.io/gh/asaskevich/govalidator) [![Go Report Card](https://goreportcard.com/badge/github.com/asaskevich/govalidator)](https://goreportcard.com/report/github.com/asaskevich/govalidator) [![GoSearch](http://go-search.org/badge?id=github.com%2Fasaskevich%2Fgovalidator)](http://go-search.org/view?id=github.com%2Fasaskevich%2Fgovalidator) [![Backers on Open Collective](https://opencollective.com/govalidator/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/govalidator/sponsors/badge.svg)](#sponsors) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator?ref=badge_shield)
6
7A package of validators and sanitizers for strings, structs and collections. Based on [validator.js](https://github.com/chriso/validator.js).
8
9#### Installation
10Make sure that Go is installed on your computer.
11Type the following command in your terminal:
12
13 go get github.com/asaskevich/govalidator
14
15or you can get specified release of the package with `gopkg.in`:
16
17 go get gopkg.in/asaskevich/govalidator.v10
18
19After it the package is ready to use.
20
21
22#### Import package in your project
23Add following line in your `*.go` file:
24```go
25import "github.com/asaskevich/govalidator"
26```
27If you are unhappy to use long `govalidator`, you can do something like this:
28```go
29import (
30 valid "github.com/asaskevich/govalidator"
31)
32```
33
34#### Activate behavior to require all fields have a validation tag by default
35`SetFieldsRequiredByDefault` causes validation to fail when struct fields do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`). A good place to activate this is a package init function or the main() function.
36
37`SetNilPtrAllowedByRequired` causes validation to pass when struct fields marked by `required` are set to nil. This is disabled by default for consistency, but some packages that need to be able to determine between `nil` and `zero value` state can use this. If disabled, both `nil` and `zero` values cause validation errors.
38
39```go
40import "github.com/asaskevich/govalidator"
41
42func init() {
43 govalidator.SetFieldsRequiredByDefault(true)
44}
45```
46
47Here's some code to explain it:
48```go
49// this struct definition will fail govalidator.ValidateStruct() (and the field values do not matter):
50type exampleStruct struct {
51 Name string ``
52 Email string `valid:"email"`
53}
54
55// this, however, will only fail when Email is empty or an invalid email address:
56type exampleStruct2 struct {
57 Name string `valid:"-"`
58 Email string `valid:"email"`
59}
60
61// lastly, this will only fail when Email is an invalid email address but not when it's empty:
62type exampleStruct2 struct {
63 Name string `valid:"-"`
64 Email string `valid:"email,optional"`
65}
66```
67
68#### Recent breaking changes (see [#123](https://github.com/asaskevich/govalidator/pull/123))
69##### Custom validator function signature
70A context was added as the second parameter, for structs this is the object being validated – this makes dependent validation possible.
71```go
72import "github.com/asaskevich/govalidator"
73
74// old signature
75func(i interface{}) bool
76
77// new signature
78func(i interface{}, o interface{}) bool
79```
80
81##### Adding a custom validator
82This was changed to prevent data races when accessing custom validators.
83```go
84import "github.com/asaskevich/govalidator"
85
86// before
87govalidator.CustomTypeTagMap["customByteArrayValidator"] = func(i interface{}, o interface{}) bool {
88 // ...
89}
90
91// after
92govalidator.CustomTypeTagMap.Set("customByteArrayValidator", func(i interface{}, o interface{}) bool {
93 // ...
94})
95```
96
97#### List of functions:
98```go
99func Abs(value float64) float64
100func BlackList(str, chars string) string
101func ByteLength(str string, params ...string) bool
102func CamelCaseToUnderscore(str string) string
103func Contains(str, substring string) bool
104func Count(array []interface{}, iterator ConditionIterator) int
105func Each(array []interface{}, iterator Iterator)
106func ErrorByField(e error, field string) string
107func ErrorsByField(e error) map[string]string
108func Filter(array []interface{}, iterator ConditionIterator) []interface{}
109func Find(array []interface{}, iterator ConditionIterator) interface{}
110func GetLine(s string, index int) (string, error)
111func GetLines(s string) []string
112func HasLowerCase(str string) bool
113func HasUpperCase(str string) bool
114func HasWhitespace(str string) bool
115func HasWhitespaceOnly(str string) bool
116func InRange(value interface{}, left interface{}, right interface{}) bool
117func InRangeFloat32(value, left, right float32) bool
118func InRangeFloat64(value, left, right float64) bool
119func InRangeInt(value, left, right interface{}) bool
120func IsASCII(str string) bool
121func IsAlpha(str string) bool
122func IsAlphanumeric(str string) bool
123func IsBase64(str string) bool
124func IsByteLength(str string, min, max int) bool
125func IsCIDR(str string) bool
126func IsCRC32(str string) bool
127func IsCRC32b(str string) bool
128func IsCreditCard(str string) bool
129func IsDNSName(str string) bool
130func IsDataURI(str string) bool
131func IsDialString(str string) bool
132func IsDivisibleBy(str, num string) bool
133func IsEmail(str string) bool
134func IsExistingEmail(email string) bool
135func IsFilePath(str string) (bool, int)
136func IsFloat(str string) bool
137func IsFullWidth(str string) bool
138func IsHalfWidth(str string) bool
139func IsHash(str string, algorithm string) bool
140func IsHexadecimal(str string) bool
141func IsHexcolor(str string) bool
142func IsHost(str string) bool
143func IsIP(str string) bool
144func IsIPv4(str string) bool
145func IsIPv6(str string) bool
146func IsISBN(str string, version int) bool
147func IsISBN10(str string) bool
148func IsISBN13(str string) bool
149func IsISO3166Alpha2(str string) bool
150func IsISO3166Alpha3(str string) bool
151func IsISO4217(str string) bool
152func IsISO693Alpha2(str string) bool
153func IsISO693Alpha3b(str string) bool
154func IsIn(str string, params ...string) bool
155func IsInRaw(str string, params ...string) bool
156func IsInt(str string) bool
157func IsJSON(str string) bool
158func IsLatitude(str string) bool
159func IsLongitude(str string) bool
160func IsLowerCase(str string) bool
161func IsMAC(str string) bool
162func IsMD4(str string) bool
163func IsMD5(str string) bool
164func IsMagnetURI(str string) bool
165func IsMongoID(str string) bool
166func IsMultibyte(str string) bool
167func IsNatural(value float64) bool
168func IsNegative(value float64) bool
169func IsNonNegative(value float64) bool
170func IsNonPositive(value float64) bool
171func IsNotNull(str string) bool
172func IsNull(str string) bool
173func IsNumeric(str string) bool
174func IsPort(str string) bool
175func IsPositive(value float64) bool
176func IsPrintableASCII(str string) bool
177func IsRFC3339(str string) bool
178func IsRFC3339WithoutZone(str string) bool
179func IsRGBcolor(str string) bool
180func IsRequestURI(rawurl string) bool
181func IsRequestURL(rawurl string) bool
182func IsRipeMD128(str string) bool
183func IsRipeMD160(str string) bool
184func IsRsaPub(str string, params ...string) bool
185func IsRsaPublicKey(str string, keylen int) bool
186func IsSHA1(str string) bool
187func IsSHA256(str string) bool
188func IsSHA384(str string) bool
189func IsSHA512(str string) bool
190func IsSSN(str string) bool
191func IsSemver(str string) bool
192func IsTiger128(str string) bool
193func IsTiger160(str string) bool
194func IsTiger192(str string) bool
195func IsTime(str string, format string) bool
196func IsType(v interface{}, params ...string) bool
197func IsURL(str string) bool
198func IsUTFDigit(str string) bool
199func IsUTFLetter(str string) bool
200func IsUTFLetterNumeric(str string) bool
201func IsUTFNumeric(str string) bool
202func IsUUID(str string) bool
203func IsUUIDv3(str string) bool
204func IsUUIDv4(str string) bool
205func IsUUIDv5(str string) bool
206func IsUnixTime(str string) bool
207func IsUpperCase(str string) bool
208func IsVariableWidth(str string) bool
209func IsWhole(value float64) bool
210func LeftTrim(str, chars string) string
211func Map(array []interface{}, iterator ResultIterator) []interface{}
212func Matches(str, pattern string) bool
213func MaxStringLength(str string, params ...string) bool
214func MinStringLength(str string, params ...string) bool
215func NormalizeEmail(str string) (string, error)
216func PadBoth(str string, padStr string, padLen int) string
217func PadLeft(str string, padStr string, padLen int) string
218func PadRight(str string, padStr string, padLen int) string
219func PrependPathToErrors(err error, path string) error
220func Range(str string, params ...string) bool
221func RemoveTags(s string) string
222func ReplacePattern(str, pattern, replace string) string
223func Reverse(s string) string
224func RightTrim(str, chars string) string
225func RuneLength(str string, params ...string) bool
226func SafeFileName(str string) string
227func SetFieldsRequiredByDefault(value bool)
228func SetNilPtrAllowedByRequired(value bool)
229func Sign(value float64) float64
230func StringLength(str string, params ...string) bool
231func StringMatches(s string, params ...string) bool
232func StripLow(str string, keepNewLines bool) string
233func ToBoolean(str string) (bool, error)
234func ToFloat(str string) (float64, error)
235func ToInt(value interface{}) (res int64, err error)
236func ToJSON(obj interface{}) (string, error)
237func ToString(obj interface{}) string
238func Trim(str, chars string) string
239func Truncate(str string, length int, ending string) string
240func TruncatingErrorf(str string, args ...interface{}) error
241func UnderscoreToCamelCase(s string) string
242func ValidateMap(inputMap map[string]interface{}, validationMap map[string]interface{}) (bool, error)
243func ValidateStruct(s interface{}) (bool, error)
244func WhiteList(str, chars string) string
245type ConditionIterator
246type CustomTypeValidator
247type Error
248func (e Error) Error() string
249type Errors
250func (es Errors) Error() string
251func (es Errors) Errors() []error
252type ISO3166Entry
253type ISO693Entry
254type InterfaceParamValidator
255type Iterator
256type ParamValidator
257type ResultIterator
258type UnsupportedTypeError
259func (e *UnsupportedTypeError) Error() string
260type Validator
261```
262
263#### Examples
264###### IsURL
265```go
266println(govalidator.IsURL(`http://user@pass:domain.com/path/page`))
267```
268###### IsType
269```go
270println(govalidator.IsType("Bob", "string"))
271println(govalidator.IsType(1, "int"))
272i := 1
273println(govalidator.IsType(&i, "*int"))
274```
275
276IsType can be used through the tag `type` which is essential for map validation:
277```go
278type User struct {
279 Name string `valid:"type(string)"`
280 Age int `valid:"type(int)"`
281 Meta interface{} `valid:"type(string)"`
282}
283result, err := govalidator.ValidateStruct(User{"Bob", 20, "meta"})
284if err != nil {
285 println("error: " + err.Error())
286}
287println(result)
288```
289###### ToString
290```go
291type User struct {
292 FirstName string
293 LastName string
294}
295
296str := govalidator.ToString(&User{"John", "Juan"})
297println(str)
298```
299###### Each, Map, Filter, Count for slices
300Each iterates over the slice/array and calls Iterator for every item
301```go
302data := []interface{}{1, 2, 3, 4, 5}
303var fn govalidator.Iterator = func(value interface{}, index int) {
304 println(value.(int))
305}
306govalidator.Each(data, fn)
307```
308```go
309data := []interface{}{1, 2, 3, 4, 5}
310var fn govalidator.ResultIterator = func(value interface{}, index int) interface{} {
311 return value.(int) * 3
312}
313_ = govalidator.Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15}
314```
315```go
316data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
317var fn govalidator.ConditionIterator = func(value interface{}, index int) bool {
318 return value.(int)%2 == 0
319}
320_ = govalidator.Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10}
321_ = govalidator.Count(data, fn) // result = 5
322```
323###### ValidateStruct [#2](https://github.com/asaskevich/govalidator/pull/2)
324If you want to validate structs, you can use tag `valid` for any field in your structure. All validators used with this field in one tag are separated by comma. If you want to skip validation, place `-` in your tag. If you need a validator that is not on the list below, you can add it like this:
325```go
326govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
327 return str == "duck"
328})
329```
330For completely custom validators (interface-based), see below.
331
332Here is a list of available validators for struct fields (validator - used function):
333```go
334"email": IsEmail,
335"url": IsURL,
336"dialstring": IsDialString,
337"requrl": IsRequestURL,
338"requri": IsRequestURI,
339"alpha": IsAlpha,
340"utfletter": IsUTFLetter,
341"alphanum": IsAlphanumeric,
342"utfletternum": IsUTFLetterNumeric,
343"numeric": IsNumeric,
344"utfnumeric": IsUTFNumeric,
345"utfdigit": IsUTFDigit,
346"hexadecimal": IsHexadecimal,
347"hexcolor": IsHexcolor,
348"rgbcolor": IsRGBcolor,
349"lowercase": IsLowerCase,
350"uppercase": IsUpperCase,
351"int": IsInt,
352"float": IsFloat,
353"null": IsNull,
354"uuid": IsUUID,
355"uuidv3": IsUUIDv3,
356"uuidv4": IsUUIDv4,
357"uuidv5": IsUUIDv5,
358"creditcard": IsCreditCard,
359"isbn10": IsISBN10,
360"isbn13": IsISBN13,
361"json": IsJSON,
362"multibyte": IsMultibyte,
363"ascii": IsASCII,
364"printableascii": IsPrintableASCII,
365"fullwidth": IsFullWidth,
366"halfwidth": IsHalfWidth,
367"variablewidth": IsVariableWidth,
368"base64": IsBase64,
369"datauri": IsDataURI,
370"ip": IsIP,
371"port": IsPort,
372"ipv4": IsIPv4,
373"ipv6": IsIPv6,
374"dns": IsDNSName,
375"host": IsHost,
376"mac": IsMAC,
377"latitude": IsLatitude,
378"longitude": IsLongitude,
379"ssn": IsSSN,
380"semver": IsSemver,
381"rfc3339": IsRFC3339,
382"rfc3339WithoutZone": IsRFC3339WithoutZone,
383"ISO3166Alpha2": IsISO3166Alpha2,
384"ISO3166Alpha3": IsISO3166Alpha3,
385```
386Validators with parameters
387
388```go
389"range(min|max)": Range,
390"length(min|max)": ByteLength,
391"runelength(min|max)": RuneLength,
392"stringlength(min|max)": StringLength,
393"matches(pattern)": StringMatches,
394"in(string1|string2|...|stringN)": IsIn,
395"rsapub(keylength)" : IsRsaPub,
396"minstringlength(int): MinStringLength,
397"maxstringlength(int): MaxStringLength,
398```
399Validators with parameters for any type
400
401```go
402"type(type)": IsType,
403```
404
405And here is small example of usage:
406```go
407type Post struct {
408 Title string `valid:"alphanum,required"`
409 Message string `valid:"duck,ascii"`
410 Message2 string `valid:"animal(dog)"`
411 AuthorIP string `valid:"ipv4"`
412 Date string `valid:"-"`
413}
414post := &Post{
415 Title: "My Example Post",
416 Message: "duck",
417 Message2: "dog",
418 AuthorIP: "123.234.54.3",
419}
420
421// Add your own struct validation tags
422govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
423 return str == "duck"
424})
425
426// Add your own struct validation tags with parameter
427govalidator.ParamTagMap["animal"] = govalidator.ParamValidator(func(str string, params ...string) bool {
428 species := params[0]
429 return str == species
430})
431govalidator.ParamTagRegexMap["animal"] = regexp.MustCompile("^animal\\((\\w+)\\)$")
432
433result, err := govalidator.ValidateStruct(post)
434if err != nil {
435 println("error: " + err.Error())
436}
437println(result)
438```
439###### ValidateMap [#2](https://github.com/asaskevich/govalidator/pull/338)
440If you want to validate maps, you can use the map to be validated and a validation map that contain the same tags used in ValidateStruct, both maps have to be in the form `map[string]interface{}`
441
442So here is small example of usage:
443```go
444var mapTemplate = map[string]interface{}{
445 "name":"required,alpha",
446 "family":"required,alpha",
447 "email":"required,email",
448 "cell-phone":"numeric",
449 "address":map[string]interface{}{
450 "line1":"required,alphanum",
451 "line2":"alphanum",
452 "postal-code":"numeric",
453 },
454}
455
456var inputMap = map[string]interface{}{
457 "name":"Bob",
458 "family":"Smith",
459 "email":"foo@bar.baz",
460 "address":map[string]interface{}{
461 "line1":"",
462 "line2":"",
463 "postal-code":"",
464 },
465}
466
467result, err := govalidator.ValidateMap(inputMap, mapTemplate)
468if err != nil {
469 println("error: " + err.Error())
470}
471println(result)
472```
473
474###### WhiteList
475```go
476// Remove all characters from string ignoring characters between "a" and "z"
477println(govalidator.WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa")
478```
479
480###### Custom validation functions
481Custom validation using your own domain specific validators is also available - here's an example of how to use it:
482```go
483import "github.com/asaskevich/govalidator"
484
485type CustomByteArray [6]byte // custom types are supported and can be validated
486
487type StructWithCustomByteArray struct {
488 ID CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` // multiple custom validators are possible as well and will be evaluated in sequence
489 Email string `valid:"email"`
490 CustomMinLength int `valid:"-"`
491}
492
493govalidator.CustomTypeTagMap.Set("customByteArrayValidator", func(i interface{}, context interface{}) bool {
494 switch v := context.(type) { // you can type switch on the context interface being validated
495 case StructWithCustomByteArray:
496 // you can check and validate against some other field in the context,
497 // return early or not validate against the context at all – your choice
498 case SomeOtherType:
499 // ...
500 default:
501 // expecting some other type? Throw/panic here or continue
502 }
503
504 switch v := i.(type) { // type switch on the struct field being validated
505 case CustomByteArray:
506 for _, e := range v { // this validator checks that the byte array is not empty, i.e. not all zeroes
507 if e != 0 {
508 return true
509 }
510 }
511 }
512 return false
513})
514govalidator.CustomTypeTagMap.Set("customMinLengthValidator", func(i interface{}, context interface{}) bool {
515 switch v := context.(type) { // this validates a field against the value in another field, i.e. dependent validation
516 case StructWithCustomByteArray:
517 return len(v.ID) >= v.CustomMinLength
518 }
519 return false
520})
521```
522
523###### Loop over Error()
524By default .Error() returns all errors in a single String. To access each error you can do this:
525```go
526 if err != nil {
527 errs := err.(govalidator.Errors).Errors()
528 for _, e := range errs {
529 fmt.Println(e.Error())
530 }
531 }
532```
533
534###### Custom error messages
535Custom error messages are supported via annotations by adding the `~` separator - here's an example of how to use it:
536```go
537type Ticket struct {
538 Id int64 `json:"id"`
539 FirstName string `json:"firstname" valid:"required~First name is blank"`
540}
541```
542
543#### Notes
544Documentation is available here: [godoc.org](https://godoc.org/github.com/asaskevich/govalidator).
545Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator).
546
547#### Support
548If you do have a contribution to the package, feel free to create a Pull Request or an Issue.
549
550#### What to contribute
551If you don't know what to do, there are some features and functions that need to be done
552
553- [ ] Refactor code
554- [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check
555- [ ] Create actual list of contributors and projects that currently using this package
556- [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues)
557- [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions)
558- [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new
559- [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc
560- [x] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224)
561- [ ] Implement fuzzing testing
562- [ ] Implement some struct/map/array utilities
563- [ ] Implement map/array validation
564- [ ] Implement benchmarking
565- [ ] Implement batch of examples
566- [ ] Look at forks for new features and fixes
567
568#### Advice
569Feel free to create what you want, but keep in mind when you implement new features:
570- Code must be clear and readable, names of variables/constants clearly describes what they are doing
571- Public functions must be documented and described in source file and added to README.md to the list of available functions
572- There are must be unit-tests for any new functions and improvements
573
574## Credits
575### Contributors
576
577This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
578
579#### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors)
580* [Daniel Lohse](https://github.com/annismckenzie)
581* [Attila Oláh](https://github.com/attilaolah)
582* [Daniel Korner](https://github.com/Dadie)
583* [Steven Wilkin](https://github.com/stevenwilkin)
584* [Deiwin Sarjas](https://github.com/deiwin)
585* [Noah Shibley](https://github.com/slugmobile)
586* [Nathan Davies](https://github.com/nathj07)
587* [Matt Sanford](https://github.com/mzsanford)
588* [Simon ccl1115](https://github.com/ccl1115)
589
590<a href="https://github.com/asaskevich/govalidator/graphs/contributors"><img src="https://opencollective.com/govalidator/contributors.svg?width=890" /></a>
591
592
593### Backers
594
595Thank you to all our backers! [[Become a backer](https://opencollective.com/govalidator#backer)]
596
597<a href="https://opencollective.com/govalidator#backers" target="_blank"><img src="https://opencollective.com/govalidator/backers.svg?width=890"></a>
598
599
600### Sponsors
601
602Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/govalidator#sponsor)]
603
604<a href="https://opencollective.com/govalidator/sponsor/0/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/0/avatar.svg"></a>
605<a href="https://opencollective.com/govalidator/sponsor/1/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/1/avatar.svg"></a>
606<a href="https://opencollective.com/govalidator/sponsor/2/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/2/avatar.svg"></a>
607<a href="https://opencollective.com/govalidator/sponsor/3/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/3/avatar.svg"></a>
608<a href="https://opencollective.com/govalidator/sponsor/4/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/4/avatar.svg"></a>
609<a href="https://opencollective.com/govalidator/sponsor/5/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/5/avatar.svg"></a>
610<a href="https://opencollective.com/govalidator/sponsor/6/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/6/avatar.svg"></a>
611<a href="https://opencollective.com/govalidator/sponsor/7/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/7/avatar.svg"></a>
612<a href="https://opencollective.com/govalidator/sponsor/8/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/8/avatar.svg"></a>
613<a href="https://opencollective.com/govalidator/sponsor/9/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/9/avatar.svg"></a>
614
615
616
617
618## License
619[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator?ref=badge_large)
620