Your first validator
In this tutorial you build a validator for an email address, run it against three inputs, and branch on the result. You need a Dart project with luthor installed. Installation covers that.
-
Create
bin/main.dartand start froml.Every validator starts from
l, the validator factory. Calling a type method such asstring()returns a validator that checks the Dart type. Each modifier you chain after it returns a new validator with one more validation.bin/main.dart import 'package:luthor/luthor.dart';void main() {final email = l.string().email().required();}l.string()checks that the value is aString..email()checks that it is an email address..required()rejectsnull, and it also changes the type:emailis aStringValidator<String>, so a successful result holds aString, not aString?. -
Validate a value.
Call
validate. It accepts any input, returns aValidationResult<String>, and never throws.isValidtells you which case you got.bin/main.dart import 'package:luthor/luthor.dart';void main() {final email = l.string().email().required();print(email.validate('bad').isValid);print(email.validate(null).isValid);}Run it with
dart run bin/main.dart. You should see:dart run bin/main.dart truefalsefalse -
Read the result.
ValidationResultis sealed with two cases,ValidationSuccessandValidationFailure. Replace the three prints with aswitch. The compiler requires both cases, and the success case gives you the typed value.bin/main.dart import 'package:luthor/luthor.dart';void main() {final email = l.string().email().required();switch (email.validate(input)) {case ValidationSuccess(:final data):print('+ $data');case ValidationFailure(:final messages):print('- $input: ${messages.first}');}}}dart run bin/main.dart - bad: value must be a valid email address- null: value is requiredThe same run as a report:
email.validate(input)+1-2- valid:
'[email protected]' - invalid:
'bad' - invalid:
null
- valid:
-
Name the value.
Messages say
valuebecause the validator has no name. Give it one withwithName, and the name replacesvaluein every message the chain produces.bin/main.dart import 'package:luthor/luthor.dart';void main() {final email = l.string().email().required();final email = l.string().email().required().withName('email');email.validate(input)+0-2- invalid:
'bad' - invalid:
null
- invalid:
-
Reuse the base validator.
Validators are immutable. Chaining returns a new validator and leaves the one you chained from unchanged, so a base validator can branch into several without one leaking into another.
final text = l.string();final email = text.email();final uuid = text.uuid();print(text.validate('anything').isValid);print(email.validate('anything').isValid);print(uuid.validate('anything').isValid);truefalsefalse
You have built a validator, run it, branched on the typed result, and named it. Next, Your first schema does the same for a map with several fields.