Skip to content

DTO Mapping and Validation

A data transfer object represents data at an external or layer boundary. It should not automatically become the persistence entity or the domain model. Separating these shapes limits accidental coupling, over-posting, lazy-loading leaks, and schema changes driven by unrelated consumers.

Different rules at different boundaries

Boundary Typical responsibility
Transport parsing Syntax, required representation fields, size and format
Application command Authorization, orchestration, use-case preconditions
Domain model Invariants that must hold for every valid state transition
Database Uniqueness, references, nullability, and durable integrity

Duplicating an invariant at a friendly boundary can improve error feedback, but the authoritative lower-level constraint must still protect concurrent writes and alternative entry points.

public record CreateAccountRequest(
        @NotBlank @Size(max = 120) String displayName,
        @NotNull @Email String email) {}

public record AccountResponse(UUID id, String displayName, String email) {}

Validation establishes that the request is well formed; it does not prove that the email is available or that the caller may create the account. Map explicitly into a command or domain operation where those rules can be enforced.

Mapping policy

Whitelist fields rather than binding a request directly onto an entity. Decide normalization once and preserve distinctions that matter: omitted versus null, replace versus merge, and client-provided versus server-owned values. For partial updates, define field-presence semantics instead of relying on Java null alone.

Mapping by hand is often clearest for small boundaries. Generated mappers reduce repetition but still need tests for ignored fields, nested mapping, defaults, enum evolution, and collection ownership. Avoid reflection-based copying that silently couples fields with the same name but different meaning.

Errors and compatibility

Return stable machine-readable error codes and safe field locations, not stack traces or persistence details. Changing a DTO can be a public API change even when the domain is unchanged. Additive fields, defaults, media types, and explicit versioning should follow the compatibility contract.

Test serialization, malformed input, boundary lengths, nested validation, unknown fields according to policy, over-posting attempts, authorization, domain invariants, and database constraints. Keep secrets out of validation messages and logs.