2026-01-26 04:12:14 +00:00
{# retoor < retoor @ molodetz . nl > #}
{% extends 'page.html' %}
2026-01-25 01:47:47 +00:00
2026-01-26 04:12:14 +00:00
{% set page_title = "wdantic" %}
{% set breadcrumb = [{"url": "api/index.html", "title": "API Reference"}, {"title": "wdantic"}] %}
{% set prev_page = {"url": "api/argparse.html", "title": "argparse"} %}
{% set next_page = {"url": "api/dataset.html", "title": "dataset"} %}
{% block article %}
2026-01-25 01:47:47 +00:00
< h1 > wdantic</ h1 >
< p > The < code > wdantic</ code > module provides data validation similar to Python's Pydantic. It includes standalone validators and a schema-based validation system for structured data.</ p >
< pre >< code > import "wdantic" for Validator, Field, Schema, ValidationResult</ code ></ pre >
< h2 > Validator Class</ h2 >
< div class = "class-header" >
< h3 > Validator</ h3 >
< p > Standalone validation functions</ p >
</ div >
< h3 > Static Methods</ h3 >
< div class = "method-signature" >
< span class = "method-name" > Validator.email</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Validates email address format.</ p >
< pre >< code > Validator.email("user@example.com") // true
Validator.email("invalid") // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > Validator.domain</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Validates domain name format.</ p >
< pre >< code > Validator.domain("example.com") // true
Validator.domain("localhost") // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > Validator.url</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Validates HTTP/HTTPS URL format.</ p >
< pre >< code > Validator.url("https://example.com/path") // true
Validator.url("ftp://example.com") // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > Validator.uuid</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Validates UUID format.</ p >
< pre >< code > Validator.uuid("550e8400-e29b-41d4-a716-446655440000") // true</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > Validator.safeStr</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Checks if string contains only printable ASCII characters (32-126).</ p >
< pre >< code > Validator.safeStr("Hello World") // true
Validator.safeStr("Hello\x00") // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > Validator.base64</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Validates Base64 encoding format.</ p >
< pre >< code > Validator.base64("SGVsbG8=") // true
Validator.base64("invalid!") // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > Validator.json</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Checks if string is valid JSON.</ p >
< pre >< code > Validator.json("{\"key\": \"value\"}") // true
Validator.json("{invalid}") // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > Validator.ipv4</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Validates IPv4 address format.</ p >
< pre >< code > Validator.ipv4("192.168.1.1") // true
Validator.ipv4("256.0.0.1") // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > Validator.minLength</ span > (< span class = "param" > value</ span > , < span class = "param" > min</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Checks minimum length of string or list.</ p >
< div class = "method-signature" >
< span class = "method-name" > Validator.maxLength</ span > (< span class = "param" > value</ span > , < span class = "param" > max</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Checks maximum length of string or list.</ p >
< div class = "method-signature" >
< span class = "method-name" > Validator.range</ span > (< span class = "param" > value</ span > , < span class = "param" > min</ span > , < span class = "param" > max</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Checks if number is within range (inclusive).</ p >
< pre >< code > Validator.range(5, 1, 10) // true
Validator.range(15, 1, 10) // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > Validator.positive</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Checks if number is positive (greater than 0).</ p >
< div class = "method-signature" >
< span class = "method-name" > Validator.negative</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Checks if number is negative (less than 0).</ p >
< div class = "method-signature" >
< span class = "method-name" > Validator.integer</ span > (< span class = "param" > value</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Checks if number is an integer (no decimal part).</ p >
< div class = "method-signature" >
< span class = "method-name" > Validator.regex</ span > (< span class = "param" > value</ span > , < span class = "param" > pattern</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Tests if value matches a regular expression pattern.</ p >
< pre >< code > Validator.regex("abc123", "^[a-z]+[0-9]+$") // true</ code ></ pre >
< h2 > Field Class</ h2 >
< div class = "class-header" >
< h3 > Field</ h3 >
< p > Factory for creating field definitions</ p >
</ div >
< h3 > Static Methods</ h3 >
< div class = "method-signature" >
< span class = "method-name" > Field.string</ span > () → < span class = "type" > StringField</ span >
</ div >
< div class = "method-signature" >
< span class = "method-name" > Field.string</ span > (< span class = "param" > options</ span > ) → < span class = "type" > StringField</ span >
</ div >
< p > Creates a string field. Options: < code > minLength</ code > , < code > maxLength</ code > , < code > pattern</ code > , < code > required</ code > , < code > default</ code > .</ p >
< div class = "method-signature" >
< span class = "method-name" > Field.integer</ span > () → < span class = "type" > IntegerField</ span >
</ div >
< div class = "method-signature" >
< span class = "method-name" > Field.integer</ span > (< span class = "param" > options</ span > ) → < span class = "type" > IntegerField</ span >
</ div >
< p > Creates an integer field. Options: < code > min</ code > , < code > max</ code > , < code > required</ code > , < code > default</ code > .</ p >
< div class = "method-signature" >
< span class = "method-name" > Field.number</ span > () → < span class = "type" > NumberField</ span >
</ div >
< div class = "method-signature" >
< span class = "method-name" > Field.number</ span > (< span class = "param" > options</ span > ) → < span class = "type" > NumberField</ span >
</ div >
< p > Creates a number field (integer or float). Options: < code > min</ code > , < code > max</ code > , < code > required</ code > , < code > default</ code > .</ p >
< div class = "method-signature" >
< span class = "method-name" > Field.email</ span > () → < span class = "type" > EmailField</ span >
</ div >
< p > Creates a field that validates email format.</ p >
< div class = "method-signature" >
< span class = "method-name" > Field.boolean</ span > () → < span class = "type" > BooleanField</ span >
</ div >
< p > Creates a boolean field.</ p >
< div class = "method-signature" >
< span class = "method-name" > Field.list</ span > (< span class = "param" > itemType</ span > ) → < span class = "type" > ListField</ span >
</ div >
< p > Creates a list field with typed items.</ p >
< div class = "method-signature" >
< span class = "method-name" > Field.map</ span > () → < span class = "type" > MapField</ span >
</ div >
< p > Creates a map/object field.</ p >
< div class = "method-signature" >
< span class = "method-name" > Field.optional</ span > (< span class = "param" > fieldDef</ span > ) → < span class = "type" > OptionalField</ span >
</ div >
< p > Makes any field optional (not required).</ p >
< h2 > Schema Class</ h2 >
< div class = "class-header" >
< h3 > Schema</ h3 >
< p > Validates data against a field definition map</ p >
</ div >
< h3 > Constructor</ h3 >
< div class = "method-signature" >
< span class = "method-name" > Schema.new</ span > (< span class = "param" > definition</ span > ) → < span class = "type" > Schema</ span >
</ div >
< p > Creates a schema from a map of field names to field definitions.</ p >
< h3 > Instance Methods</ h3 >
< div class = "method-signature" >
< span class = "method-name" > validate</ span > (< span class = "param" > data</ span > ) → < span class = "type" > ValidationResult</ span >
</ div >
< p > Validates data against the schema.</ p >
< div class = "method-signature" >
< span class = "method-name" > validateOrAbort</ span > (< span class = "param" > data</ span > ) → < span class = "type" > Map</ span >
</ div >
< p > Validates data and aborts on failure. Returns validated data on success.</ p >
< h2 > ValidationResult Class</ h2 >
< div class = "class-header" >
< h3 > ValidationResult</ h3 >
< p > Result of schema validation</ p >
</ div >
< h3 > Properties</ h3 >
< div class = "method-signature" >
< span class = "method-name" > isValid</ span > → < span class = "type" > Bool</ span >
</ div >
< p > Whether validation passed.</ p >
< div class = "method-signature" >
< span class = "method-name" > errors</ span > → < span class = "type" > List</ span >
</ div >
< p > List of ValidationError objects.</ p >
< div class = "method-signature" >
< span class = "method-name" > data</ span > → < span class = "type" > Map</ span >
</ div >
< p > Validated and coerced data (null if invalid).</ p >
< h2 > Examples</ h2 >
< h3 > Basic Schema Validation</ h3 >
< pre >< code > import "wdantic" for Field, Schema
var userSchema = Schema.new({
"name": Field.string({"minLength": 1, "maxLength": 100}),
"email": Field.email(),
"age": Field.integer({"min": 0, "max": 150})
})
var result = userSchema.validate({
"name": "Alice",
"email": "alice@example.com",
"age": 30
})
if (result.isValid) {
System.print("Valid: %(result.data)")
} else {
for (error in result.errors) {
System.print("Error: %(error)")
}
}</ code ></ pre >
< h3 > Optional Fields</ h3 >
< pre >< code > import "wdantic" for Field, Schema
var schema = Schema.new({
"title": Field.string(),
"description": Field.optional(Field.string()),
"tags": Field.optional(Field.list(Field.string()))
})
var result = schema.validate({
"title": "My Post"
})
System.print(result.isValid) // true</ code ></ pre >
< h3 > Nested Lists</ h3 >
< pre >< code > import "wdantic" for Field, Schema
var schema = Schema.new({
"numbers": Field.list(Field.integer({"min": 0}))
})
var result = schema.validate({
"numbers": [1, 2, 3, -1] // -1 will fail
})
System.print(result.isValid) // false</ code ></ pre >
< h3 > Using validateOrAbort</ h3 >
< pre >< code > import "wdantic" for Field, Schema
var schema = Schema.new({
"username": Field.string({"minLength": 3}),
"password": Field.string({"minLength": 8})
})
var data = schema.validateOrAbort({
"username": "admin",
"password": "secret123"
})</ code ></ pre >
< h3 > Standalone Validators</ h3 >
< pre >< code > import "wdantic" for Validator
var email = "user@example.com"
if (Validator.email(email)) {
System.print("Valid email")
}
var ip = "192.168.1.1"
if (Validator.ipv4(ip)) {
System.print("Valid IP address")
}
var jsonStr = "{\"key\": 123}"
if (Validator.json(jsonStr)) {
System.print("Valid JSON")
}</ code ></ pre >
< div class = "admonition note" >
< div class = "admonition-title" > Note</ div >
< p > Field types automatically coerce values when possible. For example, < code > IntegerField</ code > will convert the string < code > "42"</ code > to the number < code > 42</ code > .</ p >
</ div >
2026-01-26 04:12:14 +00:00
{% endblock %}