1
resposta

[Projeto] Duvida

No projeto final de curso do consumo da api da FIPE

eu criei uma record DadosMarcas apenas para receber os dados da marca desse jeito ( nao sei se era o mais indicado) :

@JsonIgnoreProperties (ignoreUnknown = true)
public record DadosMarcas(
        @JsonAlias("codigo") String codigo,
        @JsonAlias("nome") String nome
) {


}

beleza, ai na minha classe principal ficou dessa maneira:

 
public class Principal {
 private final String  ENDERECO = "https://parallelum.com.br/fipe/api/v1/";
    private final String MARCAS = "/marcas";
    private  Scanner leitura = new Scanner(System.in);
    private ConsumoApi consumindoApi = new ConsumoApi();
    private ConverteDados converteDadosParaJson = new ConverteDados();


    public void exibeMenu(){

        var menu  = """
                   **OPCOES**
                   -------------
                   carros
                   motos
                   caminhoes
                   --------------
                   DIGITE UMA DAS OPCOES PARA CONSULTAR
                   \n
                """;
        System.out.println(menu);
        var opcaoDigitadaPeloUsuario = leitura.nextLine().toLowerCase();


        var json = consumindoApi.obterDados(ENDERECO+opcaoDigitadaPeloUsuario+MARCAS);
        DadosMarcas dadosMarcas = converteDadosParaJson.obterDados(json, DadosMarcas.class);
        System.out.println(dadosMarcas);

acontece que como o retorno da API 'e um array de json desse maneira:

[
{
"codigo": "1",
"nome": "Acura"
},
{
"codigo": "2",
"nome": "Agrale"
},
{
"codigo": "3",
"nome": "Alfa Romeo"
},
{
"codigo": "4",
"nome": "AM Gen"
},
]

na hora de desserializar os dados

ele me retornar esse erro:

Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `com.example.ConsultaFIPE.model.DadosMarcas` from Array value (token `JsonToken.START_ARRAY`)

Alguem me da uma luz de como tratar esse json antes ou fazer minha record receber os dados em formato de lista talvez

att

1 resposta

Oi, Deivid! Tudo bem?

Podemos observar que o JSON retornado pela API é um array, mas a classe do código está esperando um objeto único, ou seja, o erro está acontecendo porque o Jackson está tentando converter um array JSON diretamente em um objeto DadosMarcas, mas DadosMarcas é definido para representar um único objeto JSON, não um array.

Para corrigir isso, precisamos modificar a desserialização para esperar uma lista de DadosMarcas em vez de um único objeto, o que podemos fazer da seguinte forma:

  1. Não precisamos alterar a classe DadosMarcas, pois ela está corretamente mapeando os campos do objeto JSON individual.

  2. Devemos alterar a desserialização para usar uma lista, de forma que na classe principal, onde fazemos a chamada para desserializar o JSON, devemos esperar uma lista de DadosMarcas em vez de um único objeto, o que pode ser feito usando um TypeReference do Jackson para informar o tipo correto durante a desserialização, deixando o código na classe principal da seguinte maneira:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;

public class Principal {
    private final String ENDERECO = "https://parallelum.com.br/fipe/api/v1/";
    private final String MARCAS = "/marcas";
    private Scanner leitura = new Scanner(System.in);
    private ConsumoApi consumindoApi = new ConsumoApi();
    private ConverteDados converteDadosParaJson = new ConverteDados();
    private ObjectMapper mapper = new ObjectMapper();

    public void exibeMenu(){
        var menu = """
                   **OPCOES**
                   -------------
                   carros
                   motos
                   caminhoes
                   --------------
                   DIGITE UMA DAS OPCOES PARA CONSULTAR
                   \n
                """;
        System.out.println(menu);
        var opcaoDigitadaPeloUsuario = leitura.nextLine().toLowerCase();

        var json = consumindoApi.obterDados(ENDERECO + opcaoDigitadaPeloUsuario + MARCAS);
        List<DadosMarcas> listaDadosMarcas = mapper.readValue(json, new TypeReference<List<DadosMarcas>>() {});
        listaDadosMarcas.forEach(System.out::println);
    }
}

Neste código, adicionamos o uso de TypeReference para especificar que estamos esperando uma lista de DadosMarcas, o que informa ao Jackson o tipo correto de objeto para desserializar o JSON.

Espero ter ajudado!

Um forte abraço e bons estudos!

Caso este post tenha te ajudado, por favor, marcar como solucionado ✓

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software