JSON Schema supports many validation keywords and data formats, as defined in the IETF memo JSON Schema Validation: A Vocabulary for Structural Validation of JSON (json-schema.org/latest/json-schema-validation.html); however, due to the restrictions of JSON itself, JSON Schema lacks the ability to define custom validation logic in the form of functions.
For example, JSON Schema does not provide a way to express the following logic: "if the age property is below 18, then the hasParentalConsent property must be set to true." Thus, if you want to perform more complicated checks, these must be done as a separate function in JavaScript. Alternatively, some JSON Schema-based validation libraries extend the JSON Schema syntax and allow developers to implement custom validation logic. For instance, the ajv validation library supports defining custom keywords.
For non-JSON Schema validation libraries, both joi and validate.js allow you to define custom validation functions.
Therefore, although JSON Schema is less expressive in theory, in practice, all solutions have the same level of expressiveness and flexibility. Because JSON Schema is a well-established standard and also more interoperable, that's the solution we will use to validate our payloads.