---
title: Conversores
---
# Quando usar um Conversor?
Quando recebemos um parametro do browser, recebemos como uma String. Por isso é necessário um conversor para fazer a tradução deste parametro para seu respectivo objeto. O VRaptor já possui registrado conversores para todos os tipos definidos na `Java Language Specification`. Para os tipos primitivos, caso o parâmetro seja recebido como `null`, será retornado o valor padrão do campo. Por exemplo, se você receber um `int` cujo valor seja `null`, o converter irá retornar `0`. Já para os tipos objetos, se o parâmetro recebido for `null` ou vazio, o valor retornado será `null`.
Por exemplo, se recebermos os seguintes parâmetros do browser:
| cliente.id | 10 |
| cliente.idade | null |
{: .content-table}
para a classe abaixo:
~~~
#!java
public class Cliente {
private Long id;
private int idade;
// getters and setters
}
~~~
Ao injetar os dados da requisição na classe, o VRaptor irá usar o conversor `LongConverter` para o campo `id` e o conversor `PrimitiveIntegerConverter` para o campo `idade`. Neste caso, o atributo `id` receberá o valor `10`, e o campo `idade` receberá o valor `0`, pois o parametro recebido é `null`.
Você pode obter a lista completa dos conversores padrão do vraptor aqui.
##BigDecimal, Double e Float localizados
São suportados utilizando o padrão de localização da sua aplicação. `Double` e `Float` são suportados tanto o tipo primitivo quanto o tipo objeto.
##Trabalhando com datas e calendários
`Calendar` e `Date` são suportados por padrão usando a localização da sua aplicação.
Existem conversores para os principais tipos do Joda-time como `DateTime`, `LocalDate`, `LocalDateTime` e `LocalTime`. Os conversores do Joda-time estão disponíveis usando o plugin [vraptor-jodatime](/pt/docs/plugins/#joda-time).
Se você está usando JDK 8, você pode tirar proveito dos conversores do pacote `java.time`, que estão disponíveis usando o plugin [vraptor-javatime](/pt/docs/plugins/#nova-api-de-datas-do-java).
##Mensagem de erro de conversão
Quando o VRaptor tenta converter um objeto, e ocorrer algum erro, é retornada para a apicação uma exception indicando o erro de conversão. Por exemplo, se você receber um parametro com valor `A` para um campo `Integer`, a conversão irá falhar e você receberá uma `ConversionException` internacionalizada. Para exibir as mensagens na sua aplicação, basta adicionar as seguintes chaves no seu resource bundle:
~~~
#!properties
is_not_a_valid_number = {0} não é um número válido.
is_not_a_valid_integer = {0} não é um inteiro válido.
is_not_a_valid_character = {0} não é um caracter válido.
is_not_a_valid_enum_value = {0} não é uma opção válida.
is_not_a_valid_date = {0} não é uma data válida.
is_not_a_valid_boolean = {0} não é um valor boolean válido.
is_not_a_valid_time = {0} não é um horário válido.
is_not_a_valid_datetime = {0} não é uma data e horário válidos.
~~~
##Definindo a localização (Locale) da aplicação
A localização dos componentes pode ser alterada utilizando a seguinte configuração no web.xml:
~~~
#!xml
javax.servlet.jsp.jstl.fmt.locale
pt_BR
~~~
Ou vocẽ pode iniciar o servidor de aplicações ou servlet container com o parâmetro:
~~~
-Duser.language=pt -Duser.region=BR
~~~
##Criando seu próprio converter
Todos os conversores devem implementar a interface `Converter` do vraptor. A classe concreta definirá o tipo que ela é capaz de converter e será invocada com o valor do parâmetro do request e o tipo alvo.
~~~
#!java
public interface Converter {
T convert(String value, Class extends T> type);
}
~~~
Além disso, seu conversor deve ser anotado com o tipo que seu conversor é capaz de converter, para isso utilize a anotação `@Convert`:
~~~
#!java
@Convert(Long.class)
public class LongConverter implements Converter { ... }
~~~
Por fim, lembre-se de dizer se seu conversor pode ser instanciado em um escopo de `Application`, `Session` ou `Request`, assim como recursos e componentes quaisquer do VRaptor. Por exemplo, um conversor que não requer nenhuma informação do usuário logado pode ser registrado no escopo de `Application` e instanciado uma única vez:
~~~
#!java
@Convert(Long.class)
@ApplicationScoped
public class LongConverter implements Converter { ... }
~~~
A seguir, a implementação de `LongConverter` mostra como tudo isso pode ser utilizado de maneira bem simples:
~~~
#!java
@Convert(Long.class)
@ApplicationScoped
public class LongConverter implements Converter {
public Long convert(String value, Class extends Long> type) {
if (isNullOrEmpty(value)) {
return null;
}
try {
return Long.valueOf(value);
} catch (NumberFormatException e) {
throw new ConversionException(new ConversionMessage("is_not_a_valid_integer", value));
}
}
}
~~~
##Populando outras propriedades de um objeto convertido
Nos exemplos acima, usamos os converters para converter um parâmetro do request em um objeto, por exemplo, parâmetro `pais` converter em um objeto `Pais`. Porém há casos onde precisamos apenas criar um objeto com alguma propriedade populada. Exemplo: para o parametro `pais.nome` podemos ter um objeto `Pais` com o atributo `nome` preenchido.
Neste caso, o `value` recebido no método será o valor do atributo `nome`. Basta então criar um converter como no exemplo abaixo:
~~~
#!java
@Convert(Pais.class)
@ApplicationScoped
public class PaisConverter implements Converter {
public Pais convert(String value, Class extends Pais> type) {
Pais pais = new Pais();
if (!isNullOrEmpty(value)) {
pais.setNome(value)
}
return pais;
}
}
~~~
##Sobrescrevendo o comportamento dos conversores existentes
Você pode sobrescrever qualquer converter já existente no VRaptor. Para isso basta estender a classe anotando-a com `@Specializes` e também adicionando a anotação `@Convert` com o tipo que será especializado. Um bom exemplo para isso é sobrescrever o conversor `BigDecimalConverter` para alterar o formato do valor.
~~~
#!java
@Specializes
@Convert(BigDecimal.class)
public class MeuBigDecimalConverter extends BigDecimalConverter {
@Override
public BigDecimal convert(String value, Class extends BigDecimal> type) {
// seu código aqui
return super.convert(value, type);
}
}
~~~
Você pode utilizar o `@Specializes` sempre que quiser reaproveitar a implementação da `superclasse`, caso contrário poderá criar um `@Alternative` com prioridade maior que a implementação do VRaptor. Como por exemplo:
~~~
#!java
@Alternative
@Priority(Interceptor.Priority.APPLICATION)
@Convert(BigDecimal.class)
public class MeuBigDecimalConverter implements Converter{
@Override
public BigDecimal convert(String value, Class extends BigDecimal> type) {
return // seu código aqui
}
}
~~~
Por padrão todo `Converter` do VRaptor tem prioridade `LIBRARY_BEFORE`.