valid() checks them, and every violation they
report is nested under the property, so the path says exactly where it is: shipping.zipCode, not zipCode.
ShippingAddress.kt
Order.kt
Nesting goes as deep as the data does: an address inside a store inside a company reports
company.store.address.street.
Which rules valid() checks
valid has a form for each way of declaring rules:
Optional and repeated objects
valid() goes inside the block of required or ifPresent, like any constraint, so null is decided first. An
optional billing address is checked only when it is there:
each runs valid() on every element, and the index joins the path:
items[1].quantity.
The order of the violations
Violations come in the order the rules are declared, with one refinement: inside one property, its own constraints come before the violations of its nested objects and elements. In::items required { each { valid() }; notEmpty() }, a notEmpty violation is reported before the violations of the
items, whatever the order of the two lines.
valid() counts as one rule. Inside failFast it is one step, with all the violations of the
nested object.