go-playground / validator

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

How to validate 'required' fields which are allowed to be an empty string ("") #1123

Closed KyleLehtinenDev closed 1 year ago

KyleLehtinenDev commented 1 year ago

Package version eg. v9, v10: v9

Issue, Question or Enhancement:

I have a use case where we are validating that an object from a rest api POST body contains all required fields which may include empty strings (""), however going off the required tag (and docs) it seems required will fail on empty values, such as 0, false, "", etc.

This causes a problem where a post body with an empty string is considered "valid" for business purposes so long as the expected object key and some string value (including "") are included. The "failure" condition would be if the 'required' object key was not included at all in the post body in any way or is an incorrect type.

When I implement our struct with 'required' tag and write test code to verify valid request bodies, our test fails due to an empty string for an object parameter. If we forgo using 'required' and try some combination of other tags (gte=0, omitempty) we have an issue where request bodies which do not include the "required" object parameter can incorrectly be validated.

Is there some combination of validators we can use to catch this edge case? I'm looking for something like "allowblank". I'm looking into creating a custom validator or just handling the edge case, but this doesn't seem too unusual a scenario that I can't help but feel I'm missing something obvious? Empty values like 0, "", false are still values and if I'm correct in understanding "required" tag will fail on empty values then this seems like a gap.

Code sample, to showcase or reproduce:

Playground

KyleLehtinenDev commented 1 year ago

I'm new to Go so I suspect there is some fundamental misunderstanding of the language on my part. Nil vs "" for string's has been discussed before: https://github.com/golang/go/issues/44219

KyleLehtinenDev commented 1 year ago

Here's my learnings for anyone else digging through this:

  1. Go considers "" as empty for a string
  2. You can use a pointer in your struct definition to distinguish between nil/empty and a value of "". You'll need to pass decoded payloads by reference to any other functions that are expecting a string reference

Playground here: https://go.dev/play/p/yT2_SpulrB6