Checks and Asserts
With checks and asserts, you can set specific rules to ensure your data’s value falls within an acceptable range.
BAML provides two types of validations:
@assert
for strict validations. If a type fails an@assert
validation, it will not be returned in the response. If the failing assertion was part of the top-level type, it will raise an exception. If it’s part of a container, it will be removed from the container.@check
for non-exception-raising validations. Whether a@check
passes or fails, the data will be returned. You can access the results of invidividual checks in the response data.
Assertions
Assertions are used to guarantee properties about a type or its components in a response. They can be written directly as inline attributes next to the field definition or on the line following the field definition, or on a top-level type used in a function declaration.
Using @assert
BAML will raise an exception if a function returns a Foo
where Foo.bar
is not between 0 and 10.
If the function NextInt8
returns 128
, BAML will raise an exception.
Asserts may be applied to a whole class via @@assert
.
Using @assert
with Union
Types
Note that when using Unions
, it is
crucial to specify where the @assert
attribute is applied within the union
type, as it is not known until runtime which type the value will be.
In the above example, the @assert
attribute is applied specifically to the
int
and string
instances of the Union
, rather than to the Foo.bar
field
as a whole.
Likewise, the keyword this
refers to the value of the type instance it is
directly associated with (e.g., int
or string
).
Chaining Assertions
You can have multiple assertions on a single field by chaining multiple @assert
attributes.
In this example, the asserts on bar
and baz
are equivalent.
Chained asserts are evaluated in order from left to right. If the first assert fails, the second assert will not be evaluated.
Writing Assertions
Assertions are represented as Jinja expressions and can be used to validate various types of data. Possible constraints include checking the length of a string, comparing two values, or verifying the presence of a substring with regular expressions.
In the future, we plan to support shorthand syntax for common assertions to make writing them easier.
For now, see our Jinja cookbook / guide or the Minijinja filters docs for more information on writing expressions.
Expression keywords
this
refers to the value of the current field being validated.
this.field
is used to refer to a specific field within the context of this
.
Access nested fields of a data type by chaining the field names together with a .
as shown below.
Assertion Errors
When asserts fail, your BAML function will raise a BamlValidationError
exception, same as when parsing fails. You can catch this exception and handle
it as you see fit.
You can define custom names for each assertion, which will be included in the exception for that failure case. If you don’t define a custom name, BAML will display the body of the assert expression.
In this example, if the quote
field is empty, BAML raises a
BamlValidationError
with the message “exact_citation_not_found”. If the
website_link
field does not contain “https://”, it raises a
BamlValidationError
with the message invalid_link.
Checks
@check
attributes add validation without raising exceptions if they fail.
Types with @check
attributes allow the checks to be inspected at
runtime.
The following example uses both @check
and @assert
. If line_number
fails its
@assert
, no Citation
will be returned by GetCitation()
. However,
exact_citation_not_found
can fail without interrupting the result. Because it
was a @check
, client code can inspect the result of the check.
You can also chain multiple @check
and @assert
attributes on a single field.
@check
, all checks on the response data are evaluated even if
one fails. In contrast, with @assert
, a failure will stop the parsing process
and immediately raise an exception. Advanced Example
The following example shows more complex minijinja expressions, see the Minijinja filters docs for more information on available operators to use in your assertions.
The Book
and Library
classes below demonstrate how to validate a book’s
title, author, ISBN, publication year, genres, and a library’s name and books.
The block-level assertion in the Library
class ensures that all books have
unique ISBNs.
In this example, we use a block-level @@assert
to check a dependency across
a pair of fields.