Annotations
Each annotation adds one modifier to the validator the generator derives from the field type. Most have a class form that takes arguments and a lowercase constant for the no-argument case: @IsEmail() and @isEmail are the same.
Class-level
Section titled “Class-level”| Annotation | Effect |
|---|---|
@luthor |
Marks the class as a model. The generator emits the five generated items for it. |
Field-level
Section titled “Field-level”| Annotation | Constant | Applies to | Adds |
|---|---|---|---|
@HasMin(n) |
String |
.min(n), a minimum length; n must be integral |
|
@HasMin(n) |
int, double, num |
.min(n), a minimum value; integral for int |
|
@HasMax(n) |
String |
.max(n), a maximum length |
|
@HasMax(n) |
int, double, num |
.max(n), a maximum value |
|
@HasLength(n) |
String |
.length(n) |
|
@Contains(s) |
String |
.contains(s) |
|
@StartsWith(s) |
String |
.startsWith(s) |
|
@EndsWith(s) |
String |
.endsWith(s) |
|
@MatchRegex(p, caseSensitive:, multiLine:, unicode:, dotAll:) |
String |
.regex(RegExp(p, ...)) |
|
@IsEmail() |
@isEmail |
String |
.email() |
@IsUri(allowedSchemes:) |
@isUri |
String |
.uri() |
@IsUrl(allowedSchemes:) |
@isUrl |
String |
.url() |
@IsIp(version:) |
@isIp |
String |
.ip() |
@IsUuid() |
@isUuid |
String |
.uuid() |
@IsCuid() |
@isCuid |
String |
.cuid() |
@IsCuid2() |
@isCuid2 |
String |
.cuid2() |
@IsDateTime() |
@isDateTime |
String |
.dateTime(); DateTime fields get it without annotation |
@IsEmoji() |
@isEmoji |
String |
.emoji() |
@IsFile(accept:) |
@isFile |
any, including package classes such as MultipartFile |
Replaces the type’s validator with l.file(); on a List<X> field, accept receives the whole list |
@WithCustomValidator(fn) |
any except Null |
.custom(fn) |
|
@WithSchemaCustomValidator(fn) |
any except Null |
.customWithSchema(fn) |
|
@luthorForwardRef |
a model type | Deprecated. It has no effect, because every nested reference is already a forward reference. Remove it. |
Every annotation except @luthor and @luthorForwardRef accepts message and messageBuilder, which pass through to the modifier. A messageBuilder has to be a top-level function or a static method. Message builders covers both.
Annotations may sit on the constructor parameter or on the field, including fields reached through super. parameters. Before 1.0 only parameters were read.
An annotation on a field type it does not apply to fails generation with an error naming the field. @HasMin(2) on a bool, @IsEmail on an int, and @HasLength on a List are errors, not silently ignored. A fractional @HasMin or @HasMax on an int or String field is also an error.
Functions passed to @WithCustomValidator, @WithSchemaCustomValidator and messageBuilder have to be top-level functions or static methods, and take the field’s type: bool isEven(int value), bool matchesPassword(String value, SchemaData data).
Modifiers are generated in the order the annotations are written. @HasMin(2) @HasMax(50) generates .min(2).max(50).
Example
Section titled “Example”bool matchesPassword(String value, SchemaData data) => value == data['password'];
enum AccountType { personal, business }
@luthor@freezedabstract class SignUp with _$SignUp { const factory SignUp({ @HasMin(2) @HasMax(50) required String name, @IsEmail() required String email, @HasMin(8) required String password, @WithSchemaCustomValidator(matchesPassword, message: 'Passwords must match') required String confirm, @HasMin(18) int? age, @IsUrl(allowedSchemes: ['https']) String? website, @Default(AccountType.personal) AccountType accountType, }) = _SignUp;
factory SignUp.fromJson(Map<String, dynamic> json) => _$SignUpFromJson(json);}final SchemaValidator $SignUpSchema = l .schema({ SignUpSchemaKeys.name: l.string().min(2).max(50).required(), SignUpSchemaKeys.email: l.string().email().required(), SignUpSchemaKeys.password: l.string().min(8).required(), SignUpSchemaKeys.confirm: l .string() .customWithSchema(matchesPassword, message: "Passwords must match") .required(), SignUpSchemaKeys.age: l.int().min(18), SignUpSchemaKeys.website: l.string().url(allowedSchemes: ["https"]), SignUpSchemaKeys.accountType: l.oneOf(["personal", "business"]), }) .withName("SignUp");$SignUpValidate(input)+1-1- valid:
{'name': 'Ada', 'email': '[email protected]', 'password': 'hunter2hunter2', 'confirm': 'hunter2hunter2', 'website': 'https://ada.dev'} - invalid:
{'name': 'Ada', 'email': '[email protected]', 'password': 'hunter2hunter2', 'confirm': 'nope', 'website': 'http://ada.dev', 'accountType': 'team'}