Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

map value validation #335

Closed
cch123 opened this issue Jan 13, 2018 · 4 comments
Closed

map value validation #335

cch123 opened this issue Jan 13, 2018 · 4 comments
Assignees
Labels

Comments

@cch123
Copy link

cch123 commented Jan 13, 2018

Package version eg. v8, v9:

v9

Issue, Question or Enhancement:

Is it possible to add map validation support

Code sample, to showcase or reproduce:

maybe like following:

validationMap := map[string]string{
    "key"  :  "gt=10",
    "key2" : "len=10"
}

targetMap := map[string]interface{} {
    "key" : "yes",
    "key2" : "anyway1234",
}

validate.Map(validationMap, targetMap)
@deankarn deankarn self-assigned this Jan 14, 2018
@deankarn
Copy link
Contributor

Hey @cch123

On a key by Key basis no, there is not support for that specific scenario; I'd add such a thing but unfortunately there would be varying opinions on exactly how it should work i.e. should all keys have to match in the maps or not....

Once logic is this specific I recommend creating custom validation, it's pretty easy :)

package main

import (
	"fmt"

	"gopkg.in/go-playground/validator.v9"
)

func main() {

	validationMap := map[string]string{
		"key":  "gt=10",
		"key2": "len=10",
	}

	validate := validator.New()
	validate.RegisterValidation("mapval", func(fl validator.FieldLevel) bool {
		m, ok := fl.Field().Interface().(map[string]interface{})
		if !ok {
			return false
		}

		for k, v := range validationMap {
			if validate.Var(m[k], v) != nil {
				return false
			}
		}

		return true
	})

	targetMap := map[string]interface{}{
		"key":  "yes",
		"key2": "anyway1234",
	}

	errs := validate.Var(targetMap, "mapval")
	fmt.Println(errs)
}

or if you want a completely generic validation function you can also pass the validation map in the context eg.

package main

import (
	"context"
	"fmt"

	"gopkg.in/go-playground/validator.v9"
)

var MapValKey = struct {
	name string
}{
	name: "validation func",
}

func main() {

	validate := validator.New()
	validate.RegisterValidationCtx("mapval", func(ctx context.Context, fl validator.FieldLevel) bool {
		m, ok := fl.Field().Interface().(map[string]interface{})
		if !ok {
			return false
		}

		vm, ok := ctx.Value(MapValKey).(map[string]string)

		for k, v := range vm {
			if validate.Var(m[k], v) != nil {
				return false
			}
		}

		return true
	})

	targetMap := map[string]interface{}{
		"key":  "yes",
		"key2": "anyway1234",
	}

	validationMap := map[string]string{
		"key":  "gt=10",
		"key2": "len=10",
	}
	ctx := context.WithValue(context.Background(), MapValKey, validationMap)

	errs := validate.VarCtx(ctx, targetMap, "mapval")
	fmt.Println(errs)
}

I did discover a bug while making these examples, so be sure to update to the latest validator.

please let me know if this helps :)

@cch123
Copy link
Author

cch123 commented Jan 15, 2018

@joeybloggs , thx a lot! This solves my problem.

@jpfluger
Copy link

This was a great example. Thanks! 👍

@JoveYu
Copy link

JoveYu commented Oct 28, 2019

@deankarn how about map in map validation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants