8
respostas

integração com terceiros

ao fazer uma integração tenho a seguinte exception: org.springframework.core.codec.DecodingException: JSON decoding error: Cannot deserialize value of type java.util.ArrayList<br.com.cursospring.apiexternateste.apiex.anuncio.model.response.Response> from Object value (token JsonToken.START_OBJECT) at org.springframework.http.codec.json.AbstractJackson2Decoder.processException(AbstractJackson2Decoder.java:275) Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): Original Stack Trace: at org.springframework.http.codec.json.AbstractJackson2Decoder.processException(AbstractJackson2Decoder.java:275) at org.springframework.http.codec.json.AbstractJackson2Decoder.decode(AbstractJackson2Decoder.java:211) at org.springframework.http.codec.json.AbstractJackson2Decoder.lambda$decodeToMono$2(AbstractJackson2Decoder.java:191) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:132) at reactor.core.publisher.MonoContextWriteRestoringThreadLocals$ContextWriteRestoringThreadLocalsSubscriber.onNext(MonoContextWriteRestoringThreadLocals.java:109) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onNext(FluxFilterFuseable.java:118) at reactor.core.publisher.Operators$BaseFluxToMonoOperator.completePossiblyEmpty(Operators.java:2071) at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:145) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:413) at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:431) at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:485) at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:712) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:113) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1383) at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1246) at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1295) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:529)

a response em json é { "id":"string", "value":[], "value":[] }

fica um hashmap, por alguma razão, nos exemplos de implementação, só que não esta mapeando id e se perde na desserialização, mas dai mesmo adiiconando no model, ele não funciona e preciso usar jsonnode pra colocar no hashmap. teria alguma alternativa melhor?

8 respostas

Oi!

Manda o código que faz a integração apra ficar melhor de entender o problema.

private static final String SEARCH_FILME_PATH = "filmes/v1/id";

    public Mono<FilmeData> pesquisaFilme(Request request) {
        return WebClient.post()
            .uri(SEARCH_FILME_PATH)
            .bodyValue(request)
            .retrieve()
            .bodyToMono(FilmeData.class)
            .doOnError(throwable -> IntegrationExceptionError.logRequestBodyError(request));
    }

A integração tá funcionando, o problema ta no FilmeData, ele não ta mapeando o hashmap que recebe, só funciona se faz a desserialização manual com json node mas não é boa pŕatica.

Duas formas de criação do model q nao deram certo:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FilmeData  {
    private String id;
    private HashMap<String, List<FilmeIntegration>>  data;
  
}
--> deste jeito, usando lombok, muda a exception, mas ainda não funciona, ele lança nullpointer em um ponto do projeto pq apesar de mapear id, ele não mapeia o hashmap, dai ele chega lá nulo.	
    
    
public class FilmeData extends HashMap<String, List<FilmeIntegration>>
    public FilmeData
        super();
    }

    public FilmeData(Map<String, List<FilmeIntegration>> data) {
        super(data);
    }
}

Entendi.

Manda aqui um json completo de exemplo que volta na resposta dessa requisição.

{ "id": "fbcb1f2089765gt6f3d48", "BannerUrl": [], "DataMovie": [ { "id_movie": "17490641-6-8fc0-62cc1ada9983", "name": "Barbie - Em uma nova aventura", "type": "filme" }, { "id_movie": "17490980-62cc1ada9983", "name": "Harry Potter", "type": "collection" } ] }

As classes para representar esse retorno da API deveriam ser assim:

public class FilmeData {

    private String id;
    
    @JsonProperty("BannerUrl")
    private List<String> bannerUrl;
    
    @JsonProperty("DataMovie")
    private List<DataMovie> dataMovie;

    // getters setters
}
public class DataMovie {

    @JsonProperty("id_movie")
    private String idMovie;
    
    private String name;
    private String type;

    // getters setters
}

Ou se preferir utilizar Record:

public record FilmeData(
        @JsonProperty("id") String id,
        @JsonProperty("BannerUrl") List<String> bannerUrl,
        @JsonProperty("DataMovie") List<DataMovie> dataMovie
) {}
public record DataMovie(@JsonProperty("id_movie") String idMovie, String name, String type) {}

desta forma recebo null, mesmo quando há valor a ser recebido, eu também achei q era list, mas na vdd "type" chave, é um chave string

no postman recebi [] e no intelli null

Manda aqui um print do postman e a url completa dessa api

oi prof, entendi o problema! agora só preciso de uma solução adequada. nenhum dos dois lados esta errado, apenas a response da api externa é complicada, pq é um map sem estar em uma propriedade no json, logo não vai pegar no model, pq não esta em um objeto raiz no json

dai fazendo uma manipulação de desserialização manual, usando jsonnode, e colocando os dados no map, funciona, porém não é legal, não é adequado

tentei algumas alternativas mas sem sucesso, sempre null ou exception, o senhor sabe como eu posso pegar esse map que não vem em um objeto raiz no json? o id vem, mas o map não, logo precisa pegar o id, pra não dar exception, e o map mapear de alguma forma, eu usei jsonnode, seria o mais adequado ou há outras soluções?

obrigada desde já