Home/Learn/Spring Boot/@RequestBody & @ResponseBody

@RequestBody & @ResponseBody

Beginner
Web / REST

@RequestBody deserialises the HTTP body into a Java object using Jackson; @ResponseBody serialises the return value back to JSON or XML.

Overview

@RequestBody binds the HTTP request body to a Java object using an HttpMessageConverter (Jackson for JSON by default). @ResponseBody writes the return value of a handler method directly to the HTTP response body, bypassing view resolution. In @RestController both are implicit on every method. Pair @RequestBody with @Valid or @Validated to trigger Bean Validation on the deserialised object. Understand how Jackson's ObjectMapper is configured — null handling, date formats, unknown property behaviour — to avoid surprise serialisation bugs.

@RequestBody with Validation

@RequestBody deserialises the incoming JSON/XML. Add @Valid to trigger JSR-303 validation immediately after deserialization. A MethodArgumentNotValidException is thrown on constraint violations.

Java — @RequestBody with @Valid and error handling
// Request DTO with validation constraints
public record CreateOrderRequest(
    @NotNull Long customerId,
    @NotEmpty List<@Valid OrderLineRequest> lines,
    @Size(max = 500) String notes
) {}

public record OrderLineRequest(
    @NotBlank String sku,
    @Min(1) @Max(100) int quantity
) {}

// Controller
@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public OrderDTO create(@RequestBody @Valid CreateOrderRequest req) {
        // If any @NotNull / @NotEmpty / @Min fails, Spring throws
        // MethodArgumentNotValidException before this method body runs
        return orderService.create(req);
    }
}

// Handle validation errors globally
@RestControllerAdvice
public class ValidationHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map<String, String> handleValidation(MethodArgumentNotValidException ex) {
        return ex.getBindingResult().getFieldErrors().stream()
            .collect(Collectors.toMap(
                FieldError::getField,
                FieldError::getDefaultMessage
            ));
    }
}

Jackson Configuration

Spring Boot auto-configures Jackson's ObjectMapper. Customise it via application.properties (spring.jackson.*) or by declaring a Jackson2ObjectMapperBuilderCustomizer bean.

Properties + Java — Jackson ObjectMapper config
# application.properties — Jackson ObjectMapper config
spring.jackson.serialization.indent-output=true
spring.jackson.deserialization.fail-on-unknown-properties=false  # ignore extra JSON fields
spring.jackson.default-property-inclusion=non_null               # skip null fields in output
spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ss.SSSZ
spring.jackson.time-zone=UTC

// Programmatic customisation
@Configuration
public class JacksonConfig {

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer customizer() {
        return builder -> builder
            .serializationInclusion(JsonInclude.Include.NON_NULL)
            .featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
            .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .modules(new JavaTimeModule())   // LocalDateTime, ZonedDateTime etc.
            .timeZone(TimeZone.getTimeZone("UTC"));
    }
}

// DTO — custom serialisation with annotations
public class OrderDTO {
    @JsonProperty("order_id")        // rename field in JSON
    private Long id;

    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime createdAt;

    @JsonIgnore                       // exclude from JSON output
    private String internalNote;
}

Streaming Large Responses

For large payloads, avoid loading the entire response into memory. Return ResponseBodyEmitter or StreamingResponseBody to stream data directly to the client without buffering.

Java — StreamingResponseBody and Server-Sent Events
// Stream a large file download
@GetMapping("/api/exports/{id}")
public ResponseEntity<StreamingResponseBody> exportOrders(@PathVariable Long id) {
    StreamingResponseBody body = outputStream -> {
        try (var writer = new OutputStreamWriter(outputStream)) {
            orderService.streamOrders(id, order ->
                writer.write(objectMapper.writeValueAsString(order) + "\n")
            );
        }
    };
    return ResponseEntity.ok()
        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=orders.jsonl")
        .contentType(MediaType.APPLICATION_OCTET_STREAM)
        .body(body);
}

// Server-Sent Events (SSE) — push real-time updates to browser
@GetMapping(path = "/api/orders/{id}/status-stream",
            produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<OrderStatus>> statusStream(@PathVariable Long id) {
    return orderService.statusUpdates(id)
        .map(status -> ServerSentEvent.<OrderStatus>builder()
            .event("status-update")
            .data(status)
            .build());
}

Key Points to Remember

  • 1@RequestBody deserialises the HTTP body via HttpMessageConverter (Jackson for JSON).
  • 2@ResponseBody writes the return value directly to the HTTP response — implicit in @RestController.
  • 3Add @Valid to @RequestBody to trigger Bean Validation; MethodArgumentNotValidException on failure.
  • 4spring.jackson.deserialization.fail-on-unknown-properties=false prevents errors on extra fields.
  • 5Use JavaTimeModule to serialise/deserialise java.time types (LocalDateTime, ZonedDateTime).
  • 6Return StreamingResponseBody or Flux for large or real-time responses without memory buffering.

Interview Questions

Sign in to ask Aria
1

What is the difference between @RequestBody and @RequestParam?

EasyInfosys
2

How does Spring validate a @RequestBody object and what exception is thrown on failure?

MediumAmazon
3

How does Jackson handle an incoming JSON field that does not exist on the Java DTO?

MediumWipro
4

How would you customise Jackson's ObjectMapper globally in Spring Boot?

MediumNetflix
5

How do you stream a large response without loading it all into memory?

HardGoogle

Ask Aria about @RequestBody & @ResponseBody

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…