In addition to validating that an element of type t has the expected form, a compound validator also applies an additional validation. For example string_and string_has_length 3 to validate that the element is a string and has a size of 3 (assuming the string_has_length x function exists).
null_and validator term checks that term is a Null and valid it using validator.
Queries over objects
As object_ returns an associative list, you have to manipulate associative list functions over and over again to validate an object correctly, fortunately there are combinators to help with object validation.
val optional_field :
?case_sensitive:bool ->(t->'aValidate.t)->string ->t->'a optionValidate.t
optional_field ?case_sensitive validator key term try to reach the value at the key position in term, if the key is not associated the function will apply the validation and wrap it into an option, if the association is not present the function will returns None. (case_sensitive act on the key and is false by default)
val optional_field_or :
?case_sensitive:bool ->default:'a->(t->'aValidate.t)->string ->t->'aValidate.t
optional_field_or ?case_sensitive ~default validator key term same of optional_field but instead of wrapping the result into an option, it will apply default if the association does not exists. (case_sensitive act on the key and is false by default)
let validate obj =
let open Validate.Applicative in
make_user
<$> required_field string "firstname" obj
<*> required_field string "lastname" obj
<*> required_field integer "age" obj
<*> optional_field_or ~default:false boolean "activated" obj
<*> optional_field string "email" obj
;;
Queries over associatives lists
In our previous example, we saw how to use queries on objects. Although this approach works, each validation requires the object to be deconstructed at each stage. Fortunately, it is possible, using associative lists, to deconstruct only once.
let's take our previous type and function (user and make_user):
let validate_with_assoc =
object_and (fun assoc ->
let open Validate.Applicative in
make_user
<$> required_assoc string "firstname" assoc
<*> required_assoc string "lastname" assoc
<*> required_assoc integer "age" assoc
<*> optional_assoc_or ~default:false boolean "activated" assoc
<*> optional_assoc string "email" assoc)
;;
The result is identical to the previous one except that this time the object is only deconstructed once.
val optional_assoc :
?case_sensitive:bool ->(t->'aValidate.t)->string ->(string * t) list->'a optionValidate.t
Same of optional_field but acting on associatives lists.
val optional_assoc_or :
?case_sensitive:bool ->default:'a->(t->'aValidate.t)->string ->(string * t) list->'aValidate.t
Same of optional_field_or but acting on associatives lists.
val required_assoc :
?case_sensitive:bool ->(t->'aValidate.t)->string ->(string * t) list->'aValidate.t
Same of required_field but acting on associatives lists.