Validator: How to allow nil, but not blank

Created on 2 Oct 2019  路  1Comment  路  Source: go-playground/validator

Package version eg. v8, v9:

v9.30

Issue, Question or Enhancement:

I have a field that is a string, that I want to allow to be null or a string, but not an empty/blank string. I can't find a way to validate this without making the field a pointer, which I can't do because then json umarshalling doesn't run.

Code sample, to showcase or reproduce:

NullString is a custom type that is a sql.NullString with a set value so I know whether an explicit NULL was sent from a json request. see: https://www.calhoun.io/how-to-determine-if-a-json-key-has-been-set-to-null-or-not-provided/

type A struct {
  Email NullString `json:"email,omitempty", validate:"omitempty,email"
}

type NullString struct {
    Set    bool
    sql.NullString
}

// more methods to this with marshal/scan/value implementations

The issue I run into with this is if I make NullString a pointer, the json unmarshalling doesn't get called, validation works as expected. If I keep NullString as is, it unmarshals correctly, but validation doesn't get called.

There are 3 ways I can see solving this:

  1. Have a special control flow called omitnil or omitnull that checks for an explicit nil instead of just a zero value. I can't seem to find a way to do this.
  2. Have a custom validator notempty validator (similar to the non-standard notblank) that checks explicitly for an empty string "". Issue is with this approach is that the validation doesn't seem to run when the value is a Nil or Zero value, even if I pass the callValidationEvenIfNull param on RegisterValdiation ( maybe this is incorrect )
  3. Use an or validation rule that specifies null or email.. though I can't figure out how to set a null, and I lose translations with the or statement. validation:eq=null|email or maybe validation:ne=|email ( this may work, just thought of it now, but would prefer not to use this method)

I would prefer not to use the 3rd option if possible

question

Most helpful comment

@dlpetrie so your validation is on the right track, but since Go's type system requires a pointer to a value eg. *string to indicate the absence of a value is where you're getting tripped up.

for example if your struct was like so, it would work:

type A struct {
  Email *string `json:"email,omitempty", validate:"omitempty,email"
}

Since NullString is always present omitempty is essentially ignored right now, what you need to do is register a CustomTypeFunc which allows you to use NullString but return the base nil or a real value in order to have omitempty to work.

There is a fully working example of this within this repo here

let me now if this helps.

>All comments

@dlpetrie so your validation is on the right track, but since Go's type system requires a pointer to a value eg. *string to indicate the absence of a value is where you're getting tripped up.

for example if your struct was like so, it would work:

type A struct {
  Email *string `json:"email,omitempty", validate:"omitempty,email"
}

Since NullString is always present omitempty is essentially ignored right now, what you need to do is register a CustomTypeFunc which allows you to use NullString but return the base nil or a real value in order to have omitempty to work.

There is a fully working example of this within this repo here

let me now if this helps.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

donileo picture donileo  路  3Comments

dumindu picture dumindu  路  5Comments

muhammadkholidb picture muhammadkholidb  路  3Comments

phenrigomes picture phenrigomes  路  5Comments

alexyans picture alexyans  路  3Comments