CodeGym /Cursos /Módulo 5. Spring /Anotaciones @RequestBody, @ResponseBody

Anotaciones @RequestBody, @ResponseBody

Módulo 5. Spring
Nivel 10 , Lección 3
Disponible

Cuando creamos un REST API, muchas veces tenemos que procesar datos que vienen en las peticiones. Por ejemplo, crear un nuevo registro o actualizar uno existente. Esos datos normalmente se envían en el cuerpo de la petición HTTP. También, cuando el servidor responde al cliente, enviamos datos de vuelta, por ejemplo en formato JSON. Ahí es donde entran en juego las anotaciones @RequestBody y @ResponseBody.

  • @RequestBody: ayuda a "extraer" datos del cuerpo de la petición HTTP y los convierte en un objeto Java que podemos usar fácilmente en el código.
  • @ResponseBody: convierte automáticamente un objeto Java a JSON (u otro formato) y lo pone en el cuerpo de la respuesta HTTP.

Es como una "teletransportación" de datos entre el cliente y el servidor. Tú mandas JSON al servidor y este se convierte mágicamente en un objeto Java normal. Y el servidor, a su vez, devuelve un objeto que mágicamente se transforma en JSON.


Trabajo con el cuerpo de la petición: @RequestBody

Spring Boot usa la librería Jackson (por defecto) para hacer las conversiones. Cuando llega una petición HTTP con JSON, la anotación @RequestBody le dice a Spring: "Ey, toma el cuerpo de la petición, parsealo y pásame un objeto Java".

Supongamos que tenemos la entidad User:


public class User {
    private String name;
    private int age;

    // Getters y setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Queremos escribir un controlador que reciba un objeto User en el cuerpo de la petición:


@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    public String createUser(@RequestBody User user) {
        // Logueamos los datos entrantes
        System.out.println("Usuario recibido: " + user.getName() + ", edad: " + user.getAge());
        return "¡Usuario " + user.getName() + " creado con éxito!";
    }
}

El cliente envía un POST:


{
    "name": "Ivan",
    "age": 30
}

Y en el servidor eso se transforma en un objeto User. No hace falta código adicional para parsear JSON — Spring se encarga de todo.


Validación de datos

A veces los datos enviados pueden ser inválidos. Por ejemplo, nombre vacío o edad negativa. En esos casos podemos usar la anotación @Valid para validación automática:


import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;

public class User {
    @NotNull(message = "El nombre no debe estar vacío")
    private String name;

    @Min(value = 0, message = "La edad no puede ser negativa")
    private int age;

    // Getters y setters
}

Y en el controlador:


@PostMapping
public String createUser(@Valid @RequestBody User user) {
    return "¡Usuario " + user.getName() + " creado con éxito!";
}

Si el cliente manda datos incorrectos, por ejemplo:


{
    "name": "",
    "age": -1
}

El servidor devolverá un error 400 Bad Request con detalles:


{
    "timestamp": "2023-10-22T10:12:45.123+00:00",
    "status": 400,
    "error": "Bad Request",
    "messages": [
        "El nombre no debe estar vacío",
        "La edad no puede ser negativa"
    ]
}

Trabajo con respuestas: @ResponseBody

Cuando necesitamos enviar datos al cliente, @ResponseBody nos echa una mano. Esta anotación le dice a Spring que el objeto Java debe convertirse en JSON (u otro formato) y formar parte de la respuesta.

¿Y sabes qué es interesante? Si usas @RestController, Spring añade automáticamente @ResponseBody a todos los métodos del controlador. Por eso los REST controllers se escriben más rápido y de forma más elegante — Spring ya se ocupa de ello por ti.

Sigamos con UserController. Ahora añadimos un método para obtener un usuario:


@GetMapping("/{id}")
public @ResponseBody User getUser(@PathVariable int id) {
    // Placeholder: devolveremos un usuario ficticio
    User user = new User();
    user.setName("Ivan");
    user.setAge(30);
    return user;
}

El cliente hace un GET:


GET /users/1

Respuesta del servidor:


{
    "name": "Ivan",
    "age": 30
}

Consejos para trabajar con @ResponseBody

  1. Puedes devolver no solo objetos, sino también colecciones. Por ejemplo:

@GetMapping
public List<User> getAllUsers() {
    List<User> users = new ArrayList<>();
    User user1 = new User();
    user1.setName("Ivan");
    user1.setAge(30);
    users.add(user1);

    User user2 = new User();
    user2.setName("Anna");
    user2.setAge(25);
    users.add(user2);

    return users;
}

Respuesta del servidor:


[
    {
        "name": "Ivan",
        "age": 30
    },
    {
        "name": "Anna",
        "age": 25
    }
]

Particularidades de la anotación

Si usas @ResponseBody con un @Controller normal (no con @RestController), no olvides añadirla a cada método que deba devolver datos en la respuesta HTTP. Por ejemplo:


@Controller
public class MyController {

    @GetMapping("/hello")
    public @ResponseBody String sayHello() {
        return "¡Hola!";
    }
}

Errores típicos al usar @RequestBody y @ResponseBody

Es importante entender cómo funcionan estas anotaciones para evitar problemas. Por ejemplo:

  1. Error de deserialización: si el JSON enviado por el cliente no coincide con la estructura del objeto, Spring lanzará una excepción. Por ejemplo, si el cliente se olvidó del campo "name", recibirás HttpMessageNotReadableException.
    • Solución: Asegúrate de que la estructura del JSON coincide con el modelo del objeto.
  2. No usar @Valid: sin validación podrías acabar con datos inválidos en la base. Usa @Valid y manejadores de errores.
  3. Ignorar los niveles de logging: registra las peticiones y respuestas JSON — te salvará tiempo al debuggear.

Aplicación práctica

@RequestBody y @ResponseBody son dos pilares sobre los que se apoya un REST API. Se encargan de toda la parte engorrosa de procesar JSON — ¡adiós al parseo manual y al formateo! En proyectos reales estas anotaciones serán tus aliados al trabajar con datos, su validación y su conversión.

Es difícil imaginar un REST API moderno sin estas anotaciones — sería como intentar programar sin un IDE. Cuando las domines, podrás crear APIs elegantes y robustas. Y, claro, no olvides probar tus endpoints — pero eso ya es otra historia.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION