go-playground / validator

:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
MIT License
16.05k stars 1.29k forks source link

Dive into and validate map keys? #1247

Open ehsandavari opened 3 months ago

ehsandavari commented 3 months ago

Package version eg. v9, v10:

v10

Issue, Question or Enhancement:

Question

Code sample, to showcase or reproduce:

package main

import (
    "fmt"
    "github.com/go-playground/validator/v10"
)

type TI18nKey string

const (
    I18nKeyInternalServer               TI18nKey = "InternalServer"
    I18nKeyBadRequest                   TI18nKey = "BadRequest"
    I18nKeyNotFound                     TI18nKey = "NotFound"
    I18nKeyUserPhoneNumberExists        TI18nKey = "UserPhoneNumberExists"
    I18nKeyPhoneNumberOrPasswordInvalid TI18nKey = "PhoneNumberOrPasswordInvalid"
)

func (r TI18nKey) String() string {
    return string(r)
}

func (r TI18nKey) IsValid() bool {
    switch r {
    case I18nKeyInternalServer,
        I18nKeyBadRequest,
        I18nKeyNotFound,
        I18nKeyUserPhoneNumberExists,
        I18nKeyPhoneNumberOrPasswordInvalid:
        return true
    default:
        return false
    }
}

type TLanguage string

const (
    LanguageEN TLanguage = "en"
    LanguageFA TLanguage = "fa"
)

func (r TLanguage) String() string {
    return string(r)
}

func (r TLanguage) IsValid() bool {
    switch r {
    case LanguageEN,
        LanguageFA:
        return true
    default:
        return false
    }
}

type Config struct {
    Messages map[TLanguage]map[TI18nKey]string `validate:"required,dive,keys,customType"`
}

func main() {
    validate := validator.New()
    validate.RegisterValidation("customType", customTypeValidator)

    messages := map[TLanguage]map[TI18nKey]string{
        LanguageEN: {
            I18nKeyInternalServer: "en internal server error",
            "NotRegisteredKey":    "in this case expect validator return validation error",
        },
        LanguageFA: {
            I18nKeyInternalServer: "fa internal server error",
            "NotRegisteredKey":    "in this case expect validator return validation error",
        },
        "NotRegisteredLanguage": {}, // in this case validator is return error : its true
    }

    err := validate.Struct(Config{Messages: messages})
    if err != nil {
        fmt.Printf("messages not valid! %s\n", err)
    }
}

type iCustomTypeValidatorValidator interface {
    IsValid() bool
}

func customTypeValidator(fl validator.FieldLevel) bool {
    value := fl.Field().Interface().(iCustomTypeValidatorValidator)
    return value.IsValid()
}