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

Is it possible to make a field both optional and required ONLY if the field is added? #158

Open
darienmiller88 opened this issue Nov 15, 2021 · 2 comments

Comments

@darienmiller88
Copy link

So, I've ran into a rather unique use case that may or may not be supported. Is it possible to validate a string field that is made optional, and if included in the request body, return an error if it is either empty or not in a desired range?

With the following validation, I am checking the request body to see if any of the following fields are added, and IF they are, check the field to see if it passes the validation. However, the issue I am running empty values are allowed to pass the validation, and adding required cause the field/key to be required as opposed to the just the value. Is there any way to accomplish optional field validation, that doesn't treat empty values as passing?

Here is my validation schema:

err := validation.Errors{
		"reminder": validation.Validate(data["reminder"], validation.Length(3, 50),
		"time": validation.Validate(data["time"], validation.Match(regexp.MustCompile("^([1-9]|1[0-2]):[0-5][0-9]\\s(AM|PM)$")).Error("Time must be of the form \"12:30 AM\".")),
		"date": validation.Validate(data["date"], validation.Date("2006-01-02")),
	}.Filter()

For example, this request should pass since it passes the time field, even though the other field are not added.

{ 
    "time": "1:30 AM"
}

And this one shouldn't since the reminder field is empty (but it still does):

{
    "time": "1:30 AM",
    "reminder": ""
}
@mattwelke
Copy link

mattwelke commented Aug 15, 2022

I came across this today when evaluating this library as a potential replacement for JSON Schema for API request body validation.

I took an example from the current README file and changed it to a minimal example to test an optional property with a minimum and maximum length:

package main

import (
	"fmt"

	validation "github.com/go-ozzo/ozzo-validation/v4"
)

func main() {
	c := map[string]interface{}{
		// "Name": "Qiang Xue",
	}

	err := validation.Validate(c,
		validation.Map(
			// Name, if provided, must have a length between 1 and 20.
			validation.Key("Name", validation.Length(1, 20)),
		),
	)
	fmt.Println(err)
}
Name: required key is missing

Looks like right now, this still isn't supported. If anyone runs into this use case, I can recommend JSON Schema as a way to do it if your data happens to come in as JSON, or you're comfortable serializing it to JSON, performing validation, then deserializing it (https://github.com/xeipuuv/gojsonschema).

There's also an older, struct tag based library that I know from experience works well for this use case (https://github.com/go-playground/validator). This is ideal if your not yet validated data doesn't come in as JSON. For us, this didn't work well, and we ended up switching from it to the JSON Schema library.

We switched because we found that the error messages weren't as useful if the data that came in wasn't "valid enough" to be parsed into a Go struct, and it needed to be parsed into a struct to be validated with the struct tag library in the first place. Doing validation on the HTTP request body string with JSON Schema and then parsing the data to a Go struct (which is guaranteed to succeed for data valid according to our JSON Schema schema) ended up being better for us.

@lingjhf
Copy link

lingjhf commented Apr 3, 2023

https://pkg.go.dev/github.com/go-ozzo/ozzo-validation/[email protected]#KeyRules.Optional @mattwelke

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

No branches or pull requests

3 participants