Spring Boot: From Basics to Production · Building REST APIs with Spring MVC

DTOs with Records and JSON Mapping

Model requests and responses with Java records and control JSON output.

Java records are ideal DTOs: immutable, concise, with built-in equals/hashCode. Use separate request and response records, map between entities and DTOs in services (manually or with MapStruct), and configure Jackson for dates (ISO-8601), naming and unknown properties. Annotations like @JsonProperty and @JsonInclude(NON_NULL) fine-tune output.

public record CreateProductRequest(
        @NotBlank @Size(max = 200) String name,
        @NotNull @PositiveOrZero Long priceCents,
        @NotBlank String currency) {}

@JsonInclude(JsonInclude.Include.NON_NULL)
public record ProductResponse(long id, String name, long priceCents, String currency, Instant createdAt) {
    static ProductResponse from(Product p) {
        return new ProductResponse(p.getId(), p.getName(), p.getPriceCents(), p.getCurrency(), p.getCreatedAt());
    }
}

Common pitfalls

  • Using double for money.
  • One DTO for create, update and response (clients can set server-controlled fields).
  • Leaking internal enums or IDs you may want to change later.

Key points

  • Records as DTOs
  • Separate request/response types
  • Instant/ISO-8601 for timestamps

Further reading: Spring Boot: JSON

Practice questions

Why are records good DTOs?

Answer

They're immutable, concise, and their components define the JSON shape clearly; Jackson supports them natively.

Why separate CreateProductRequest from ProductResponse?

Answer

Requests shouldn't include server-generated fields (id, createdAt), and responses may include computed or related data; separate types keep the contract explicit and safe.

Open in the app to mark lessons complete, take notes and track your progress.