Open cachesdev opened 1 month ago
Yes I agree. This is already planned. Probably for v0.10 I have a working prototype in a local branch.
The approach of validating a struct is fine but it does have some limitations:
Also, v0.9 will come with an update to the zhttp package which will handle json also. I think there is merit to recommending you use the zog implementation because we can introduce future performance improvements during parsing. You will be able to do schema.Parse(zhttp.Request(r), &dest)
and it will parse into the destination. This will still under the hood parse the body into a map first but this can be optimized out at a later point.
A part from that I do agree 100% that this needs to be implemented. The prototype I have locally has the api of schema.Validate(&data)
. There are a few considerations we have to make though, the main being that this will make two conceptually similar functions that will work VERY differently in practice.
For example, Parse right now will check for require based on the input data. That means that the results here are different based on if you use Parse or Validate:
// imagine this is the json we get from the request & we have a
s := `
{
"name": "hello"
}
`
var o struct {
Name int `json:"name"`
}
oSchema = z.Struct(z.Schema{"name": z.Int().Required()}).Required()
err := c.Bind(&o) // This will return an error that it cannot parse hello into name
oSchema.Validate(&o) // this will return an error that o is required but it is 0
oSchema.Parse(zhttp.Request(c.Request()), &o) // This will return an error failed to coerce "hello" into an integer
Most of this weird behaviours are actually quite intuitive once you stop to think about them for a bit but it is still the case that one single schema is behaving in two different ways.
Some other concerns:
since Validate
would be depending on the result of a different unmarshaller, it makes sense that it would have different errors in case Bind
fails. I can see your point, using zhttp makes more sense in this case (and if it's faster with better errors, then why not)
PreTransforms could make sense, but I can't think of many cases where you would want to do this. as for default and catch, it makes sense to remove them for Validate
as it wont be able to modify the object being validated either way
Hey @cachesdev, I have been busy last few days. But I have had some time to think about this and....
I don't excluding features from the schema when calling the Validate
method. Because I think it will be confusing for users. Therefore I have decided to basically bite the bullet and implement Validate in such a way that all schema components will work (transforms, defaults, etc). This just means it will take me a little bit longer to get it out since it is more complex than I initially thought.
For now, I would recommend to use the zhttp package if working with json I have added better references to it in the docs and the API should be very nice now. This will all go out in 0.9 which I plan on releasing tonight. It will also include the i18n code you contributed and a few other minor tweaks.
I think I mentioned before but this is what the ergonomics for using the zhttp library will look like now:
errs := userSchema.Parse(zhttp.Request(r), &user)
As to when this will be done I don't know yet but this and pointer support will be my next priorities
I am rewriting my endpoints to use zhttp and everything is working great. great work as always. I do see the benefit of Validate having full support, pretransforms and such may not have a lot of use but I bet there may be an edge case or two where it may be appreciated, as I said before I can't think of many reasons to use it but there could still be reasons to do it.
Currently. zog handles both data unmarshaling and validation with
Parse
, which is great when you are using the standard library. whoever, this leads to duplicated unmarshalling in other http frameworks, in my case, echo:a more memory and performance efficient code may look like this:
the utility of this is not only limited to this case, it can also be useful when you already have data from somewhere else and you just want to validate it:
my proposal is to either create a
Validate
method, or be able to passnil
toParse
. or do both, being able to passnil
toParse
and create aValidate
method that wraps it for a better API.