Ciro
Posted on November 7, 2022
En la publicación anterior vimos cómo crear conversores personalizados para propiedades dentro de una clase anotada con @RequestBody
.
En esta ocasión veremos cómo hacer la misma lógica para parámetros anotados como @RequestParam
.
Refactorizando el ejemplo de la publicación anterior, supongamos que tenemos el siguiente controlador:
@RestController
@AllArgsConstructor
@RequestMapping("transactions")
public class CreateTransactionController {
@PostMapping
public ResponseEntity<CreateTransactionOutputDto> createTransaction(
@RequestParam Double amount,
) {
//
}
}
Y enviamos una petición a este endpoint con los siguientes parámetros:
POST '{{apiUrl}}/transactions?amount=45.13'
Por defecto Spring será capaz de enlazar cada elemento de la petición con su correspondiente parámetro de nuestro controlador, siempre y cuando encuentre el conversor adecuado para ello.
No tendremos problemas si declaramos parámetros de tipo primitivo o sus wrappers, pero en caso de querer enlazarlos a una clase, debemos crear un conversor.
Cómo mapear Value Objects
Supongamos ahora que actualizamos el tipo de clase del parámetro de la siguiente manera:
// file: Money
public record Money(Double value) {...} // <- Creamos un record para encapsular un elemento de tipo Money
// file: CreateTransactionController
@PostMapping
public ResponseEntity<CreateTransactionOutputDto> createTransaction(
@RequestParam Money amount, // <- Actualizamos el tipo parámetro
) {
//
}
Para que Spring sea capaz de convertir estos datos correctamente, creamos el conversor extendiendo de org.springframework.core.convert.converter.Converter
:
import org.springframework.core.convert.converter.Converter;
public class MoneyConverter implements Converter<String, Money> { // <- Implementamos la interfaz Converter
@Override
public Money convert(String source) {
return new Money(Double.parseDouble(source)); // <- Implementamos la conversión con la lógica que deseemos
}
}
Una vez más, se trata de un código muy simple. Únicamente es necesario implementar la infertaz Converter
indicando como tipo de parámetros la clase de entrada y la de salida, en este caso indicamos que se va a convertir una String
en la clase Money
.
Por último, debemos indicar a Spring que se utilice este conversor para mapear las instancias de la clase Money
, incluyendo el nuevo conversor dentro del registro de formateadores:
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new MoneyConverter()); // <- Instanciamos e incluimos nuestro conversor
}
}
Una vez hecho esto, Spring será capaz de utilizar nuestro conversor cuando intente mapear propiedades de tipos distintos a los primitivos/wrappers o las clases para las que ya cuenta con conversores.
Posted on November 7, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.