Validating Request Data
1. Implementing Schema Validation
| Tool | Use |
|---|---|
| JSON Schema (Draft 2020-12) | Standard schema validation |
| OpenAPI 3.1 | Inherits JSON Schema 2020-12 |
| Bean Validation (Java) | Annotation-based: @NotNull, @Size, @Email |
| Zod / Joi (Node) | Programmatic schemas |
| Pydantic (Python) | Type-hint validation |
2. Validating Required Fields
Example: Bean Validation (Java)
public class CreateUserRequest {
@NotBlank(message = "Name is required")
private String name;
@NotBlank @Email
private String email;
@NotNull @Min(18) @Max(120)
private Integer age;
}
3. Validating Data Types
| JSON Type | Validation |
|---|---|
| string | type: string, minLength, maxLength, pattern |
| integer / number | minimum, maximum, multipleOf |
| boolean | type: boolean (no "true" string) |
| array | minItems, maxItems, uniqueItems, items |
| object | required, properties, additionalProperties |
4. Validating String Formats
| Format | Pattern / Example |
|---|---|
email | RFC 5322 |
uri | RFC 3986 |
uuid | RFC 4122 |
date | 2026-05-15 |
date-time | 2026-05-15T10:30:00Z |
ipv4 / ipv6 | RFC 2673 |
hostname | RFC 1034 |
5. Validating Number Ranges
| Constraint | JSON Schema | Bean Validation |
|---|---|---|
| Min (inclusive) | minimum: 0 | @Min(0) |
| Min (exclusive) | exclusiveMinimum: 0 | @DecimalMin(value="0", inclusive=false) |
| Max | maximum: 100 | @Max(100) |
| Multiple of | multipleOf: 0.01 | @Digits(integer=10, fraction=2) |
6. Validating String Length
| Constraint | JSON Schema | Bean Validation |
|---|---|---|
| Min length | minLength: 1 | @Size(min=1) |
| Max length | maxLength: 255 | @Size(max=255) |
| Exact length | minLength=maxLength=N | @Size(min=N, max=N) |
| Regex | pattern: "^[A-Z]{3}$" | @Pattern(regexp="^[A-Z]{3}$") |
7. Validating Array Items
Example: Array Validation (JSON Schema)
{
"type": "array",
"minItems": 1,
"maxItems": 10,
"uniqueItems": true,
"items": {
"type": "string",
"format": "email"
}
}
8. Implementing Custom Validation Rules
Example: Custom Cross-Field Validator (Java)
@Constraint(validatedBy = DateRangeValidator.class)
@Target(TYPE) @Retention(RUNTIME)
public @interface ValidDateRange {
String message() default "End date must be after start date";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class DateRangeValidator implements ConstraintValidator<ValidDateRange, BookingRequest> {
public boolean isValid(BookingRequest req, ConstraintValidatorContext ctx) {
return req.getEndDate().isAfter(req.getStartDate());
}
}
9. Returning Validation Errors
| Status | Use Case |
|---|---|
| 400 Bad Request | Malformed JSON, syntax error |
| 422 Unprocessable Entity | Valid JSON, business rule violation |
10. Providing Field-Level Error Messages
Example: Field-Level Error Response
{
"type": "https://example.com/errors/validation",
"title": "Validation Failed",
"status": 422,
"errors": [
{"field": "email", "code": "INVALID_FORMAT", "message": "Must be valid email"},
{"field": "age", "code": "OUT_OF_RANGE", "message": "Must be 18-120"},
{"field": "tags[2]", "code": "TOO_LONG", "message": "Max 20 characters"}
]
}