Jh123x / go-validate

A go data validation library
http://portfolio.jh123x.com/go-validate/
MIT License
5 stars 0 forks source link

Feature: Handling structs and maps #10

Closed anjolaoluwaakindipe closed 6 months ago

anjolaoluwaakindipe commented 7 months ago

This library is very good at making one off validations for most types but the documentation does not present a very easy way to pass multiple options without repeatedly passing in the same variable/value. This will make it easier to implement validations for structs and maps.

Jh123x commented 7 months ago

This library is very good at making one off validations for most types but the documentation does not present a very easy way to pass multiple options without repeatedly passing in the same variable/value. This will make it easier to implement validations for structs and maps.

What do you have in mind for this?

Jh123x commented 7 months ago

This library is very good at making one off validations for most types but the documentation does not present a very easy way to pass multiple options without repeatedly passing in the same variable/value. This will make it easier to implement validations for structs and maps.

I can think of a few different ways.

  1. Pass a struct into a validator
    • Pass Struct Validators (Different validators) into the validator to check the fields
    • Check struct by name using reflection
    • Slower runtime
  2. Pass struct values into each validator (current implementation)
  3. Implement your validators for your custom structs (Can be extended based on use case)
    • Use options.WithRequire or implement ttypes.Validator
func ValidateStruct(value YourStruct) ttypes.Validator {
    return func() error {
        // Add checks here and return errors that you want
    }
}

Number 1 has a runtime speed tradeoff for convenience while being more error-prone to implement.

Number 2 is when the validation is 1 off for the struct, which should not be too much of an issue.

Number 3 is the way to go if you have some custom use case that requires validating a particular struct a lot. Once you have implemented your validator, you can use it together with the validators defined in this project.

Jh123x commented 7 months ago

Are you looking for something like this?

a := "b"
ValidateValue(a).WithValidator(
    options.IsNotEmpty,
    options.IsLength(10),
)
anjolaoluwaakindipe commented 7 months ago

That approach is something I was looking for. I do agree with the points you made, I just think that there should be a way to implement something similar to zod's validation without requiring as much reflection as ozzo-validation. Maybe instead of a generic function that handles every possible value type that could be passed. You can streamline the validation to be more type specific which should not slow down runtime as much, since only a little to no reflection is required. Example:

a := "b"
c := 1
err :=Validator(
    ValidateString(a).IsNotEmpty().IsLength(10),
    ValidateInt(b).Min(-1).Max(3)
).validate()

// or 
msg := "hello"
err := ValidateString(msg).IsNotEmpty().Contains("hello").validate()

This might help improve convenience while not slowing down runtime by a considerable margin

Jh123x commented 7 months ago

That approach is something I was looking for. I do agree with the points you made, I just think that there should be a way to implement something similar to zod's validation without requiring as much reflection as ozzo-validation. Maybe instead of a generic function that handles every possible value type that could be passed. You can streamline the validation to be more type specific which should not slow down runtime as much, since only a little to no reflection is required. Example:

a := "b"
c := 1
err :=Validator(
    ValidateString(a).IsNotEmpty().IsLength(10),
    ValidateInt(b).Min(-1).Max(3)
).validate()

// or 
msg := "hello"
err := ValidateString(msg).IsNotEmpty().Contains("hello").validate()

This might help improve convenience while not slowing down runtime by a considerable margin

I've added a slightly different version of what is mentioned here. Please let me know what you think 👍

anjolaoluwaakindipe commented 6 months ago

This is a more convenient version and I feel like this is the right direction for this library!

Jh123x commented 6 months ago

This is a more convenient version and I feel like this is the right direction for this library!

I've started on another repo which aims to be a go port of zod using reflection. https://github.com/Jh123x/go-zod

It uses reflection which may lead to slower code.