Conversores personalizados para @RequestParam
Tags: spring, java, spanish
Published: 2022-11-07 08:00:00

En la [publicación anterior](https://dev.to/gekyzo/conversores-personalizados-para-requestbody-37hp) 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:

```java
@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:

```java
// 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`:

```java
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:

```java
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.