Replies: 4 comments 23 replies
-
I like this approach to cover the validations and I do agree that this is not going to cover all possible use cases that we can have, but in my opinion, is a good way to follow. JSON schema has been widely used in micro service architectures as constraints/validations between API contracts. Also in some cases to build dynamic ui pages and forms. One of the areas I faced and found not trivial to achieve is nesting schemas that are defined in different endpoints.
Well these are some of my concerns about this approach (which I'm not seeking for answers) that of course they can be implemented, but I'm just put them on top of the table to be considered as part of the overall architecture of this solution. |
Beta Was this translation helpful? Give feedback.
-
Another option would be to build something similar or reuse the Laravel validation system, which I found to be more approachable than a JSON schema https://laravel.com/docs/11.x/validation#available-validation-rules For Checkout additional fields, we're looking into adding visibility rules, (doc here). Ideally if we're going to come with a validation system, it should look slightly similar to that one and ideally can both be used together (under the same definition). |
Beta Was this translation helpful? Give feedback.
-
One main concern I have with JSON is the complexity of the system, and lack of ability to get dynamic-ish values. Store API Schema for example has a good amount of boilerplate in it, would it be possible that developers write a simpler version of the rules that gets translated down the road to JSON? |
Beta Was this translation helpful? Give feedback.
-
Sharing some thoughts I had previously shared privately. While JSON Schema does provide some level of validation, the schemas can get complicated to express and then become bloated themselves. Depending on what you do, it might be worth checking into Zod, which @sirreal introduced into some other projects. Zod won’t validate the types on the server, but it does provide an arguably more convenient way to express the types of data (because it’s composable and code-oriented) while providing auto-completion inside the JS/TS code. Once you parse a document with what Zod auto-generates, it’s guaranteed to be valid, vs. JSON Schema where it can be hard to properly validate certain constraints. |
Beta Was this translation helpful? Give feedback.
-
Within various places around Woo, we have more and more cases where client-side validation proves beneficial.
Unfortunately, we don't have any real patterns for this so far and we seem to be taking a multitude of approaches to try and solve the same problem.
Current validation patterns
Typically our approaches when building out more modern user interfaces falls into one of two buckets; both of which have their pitfalls.
Custom client-side validation
The new product editor contains many fields which must be validated prior to saving products. Many of these fields implement custom blocks for the sake of being able to add their own validation logic within the block. Others are able to circumvent the need for custom blocks by using helper properties that handle validation within the templating API.
While this does seemingly offer a better experience, it can easily lead to the server and client becoming out of sync when it comes to those validation rules. As seen in the product editor, existing records have the potential to be completely valid in the previous experience, but can't be saved in the new experience given the introduction of client-side validation. (see pcQJnU-2nH-p2)
Server-side only validation
As an alternative to this, we can keep the single source of truth on the server and do validation there. The checkout block is extensible with additional fields from third parties. Currently, validation for these fields are handled on the server.
While this clearly leads to less errors and is a more stable approach, it also requires more round trips to the server to show validation errors and ultimately creates a much slower user experience for customers at a time when speed and reduction in friction is most important.
Why use JSON schema
Using JSON schema allows us to declare validation rules and properties to cover a large number of our validation cases. It is well-documented and allows us to easily extend our current schemas to support the necessary validation. But beyond that, it offers a solution to the bigger issues we're facing with validation right now:
1. Single source of truth
The biggest reason to use JSON schema is it gives us a sane way of understanding validation logic across both the client and server. This means that because they are using the same ruleset, there's little room for validation to become out of sync where server validation might pass, but client-side fails.
It also provides a self-documenting object that describes how data should be presented and allows easy reuse of validation rules going forward in different contexts.
2. Improved user experience
Because the validation can easily be used in the client, we don't need to call the server to check if a field is valid in many cases and can show errors in realtime as they are typed.
3. Easier third party integration
It allows for 3PDs to add validation logic in PHP via hooks that already exist. This reduces the need to spin up custom components or blocks in order to write validation logic in Javascript when generic block types already exist to extend existing experiences.
Proof of Concept
I put together a quick concept that shows how we can use JSON schema. The concept is pretty simple and piggybacks on our existing product endpoint schema. In brief:
Issues that need more discussion
Despite all the positives that come with JSON schema, it is not perfect and there are areas that need more thought/discussion.
Complex validation use cases
While JSON Schema has come a long way and probably meets the needs of 95%+ of cases, there are some fields that are too complex to be handled purely in JSON or break the schema.
A field wanting to set a minimum amount based on another field can be handled by JSON schema, but a field wanting to set a limit based on a percentage of another field may be significantly more challenging to handle via pure JSON.
There are also cases that while possible to achieve, would be needlessly complex via JSON alone and validation on the server makes a lot more sense. For example, validating that a slug is unique is something we still want the server to handle as opposed to providing an irrationally long list of exclusions via JSON schema.
Related to the point below, but it is possible to declare custom keywords that may be able to handle this, but we would need to push towards having consistent dialect on both the client and server. Maintaining an organized package with all the validation logic would go a long way in making sure we can accomplish this.
Coerced types or non-conforming specs
Some fields, such as
regular_price
, would benefit from being anumber
type to allow usage of all the validation rules around numbers. However, WooCommerce treats prices as strings, meaning rules likeexclusiveMinimum
do not apply to this data type.We can either set this type to
number
and attempt to coerce the string to a number at runtime during validation or we can create rules that aren't in the spec, such asexclusiveMinimumCoerced
that allow keeping the type untouched while declaring a new rule to apply to this type.On a side note, the Ajv package does offer an option to coerce data types but it's buggy when it comes to referencing other fields within the schema.
Error message consistency
The POC shows a way to provide error messages per each scenario as part of the schema. However, realistically we often have differing language when it comes to error messages on the client and server.
We need to pick between either providing consistent error messages or providing another API to intercept errors and provide messages based on error type and context.
Bundle size
Finally, it's also worth noting that package used for the client-side validation, Ajv, comes in at 119kb minified and 35kb when gzipped. While not extremely large, this is a non-insignificant amount. If we plan to use this on the frontend of the site, it may be worthwhile to consider creating a package that's a bit more stripped down and lighter weight to accomplish what we need.
Thoughts or concerns
Personally, I feel it's a pretty easy call to green-light this project since the benefits far outweigh the drawbacks. The only concerns I have currently are listed above and mostly just discussions that need decisions, not blockers.
But all feedback is welcome on this and if there are cases where this does not adequately fit project needs, I'd love to know what those are. Obviously JSON schema will not solve 100% of use cases, but if it can solve the overwhelming majority of cases, we should consider this approach to validation.
Beta Was this translation helpful? Give feedback.
All reactions