当前位置: 首页 > 知识库问答 >
问题:

Spring Web客户端返回异常”body不支持内容类型'应用程序/json'Type=[响应对象]

郝冥夜
2023-03-14

我使用web客户端发布第三方API,第三方API返回如下响应:

{
    "RetailTransactionGenericResponse": {
        "authID": 1146185,
        "product": {
            "amount": 20,
            "balance": 0,
            "status": "D",
            "metafields": {
                "metafield": [
                    {
                        "name": "serialNum",
                        "value": 8095843490
                    }
                ]
            }
        },
        "responseCode": 0,
        "responseText": "Success",
        "transactionID": "b0924cca-f2a9-477f-915b-9153e74ebce0"
    }
}

因此,在我的payload包中,它有RetailTransactionGenericResponseWrapper类,其中包含RetailTransactionGenericResponse类。

这里是RetailTransactionGeneric响应类的代码

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;

@Data
@ToString
@Builder
@AllArgsConstructor(onConstructor_ = @JsonCreator)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class RetailTransactionGenericResponse {

    @JsonProperty
    private String authID;

    @JsonProperty
    private Product product;

    @JsonProperty
    private String responseCode;

    @JsonProperty
    private String responseText;

    @JsonProperty
    private String transactionID;
}

对于产品

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Product {

    @JsonProperty
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private double amount;

    @JsonProperty
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String code;

    @JsonProperty
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String upc;

    // Response part

    @JsonProperty
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private MetaFields metafields;

    @JsonProperty
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String balance;

    @JsonProperty
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String status;

    @Override
    public String toString() {
        return ReflectionToStringBuilder.toString(this, ToStringStyle.JSON_STYLE);
    }
}

对于元字段

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.util.List;

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MetaFields {

    @JsonProperty
    private List<MetaField> metafield;
}

元字段

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MetaField {

    @JsonProperty
    private String name;

    @JsonProperty
    private String value;
}

所以在我的服务中,我是如何找回回应的

RetailTransactionGenericResponseWrapper response =
    webClient.post().uri(url).headers(headers -> headers.setBearerAuth(token)).accept(APPLICATION_JSON)
        .body(Mono.just(retailTransactionGenericRequest), RetailTransactionGenericResponseWrapper.class)
        .retrieve().bodyToMono(RetailTransactionGenericResponseWrapper.class).block();

我做错了什么,它无法将json映射到对象?

这里是异常堆栈

ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.reactive.function.client.WebClientResponseException: 200 OK from POST https://[third_party_url]; nested exception is org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/json' not supported for bodyType=com.xxx.xxx.payload.xxx.RetailTransactionGenericResponseWrapper] with root cause
org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/json' not supported for bodyType=com.xxx.xxx.payload.xxx.RetailTransactionGenericResponseWrapper
    at org.springframework.web.reactive.function.BodyExtractors.lambda$readWithMessageReaders$12(BodyExtractors.java:201)
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ⇢ Body from POST https://[third_party_url] [DefaultClientResponse]
Stack trace:
        at org.springframework.web.reactive.function.BodyExtractors.lambda$readWithMessageReaders$12(BodyExtractors.java:201)
        at java.base/java.util.Optional.orElseGet(Optional.java:369)
        at org.springframework.web.reactive.function.BodyExtractors.readWithMessageReaders(BodyExtractors.java:197)
        at org.springframework.web.reactive.function.BodyExtractors.lambda$toMono$2(BodyExtractors.java:85)
        at org.springframework.web.reactive.function.client.DefaultClientResponse.body(DefaultClientResponse.java:132)
        at org.springframework.web.reactive.function.client.DefaultClientResponse.bodyToMono(DefaultClientResponse.java:147)
        at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultResponseSpec.lambda$bodyToMono$2(DefaultWebClient.java:541)
        at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125)
        at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:73)
        at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:120)
        at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79)
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199)
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199)
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199)
        at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82)
        at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2346)
        at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribeInner(MonoFlatMapMany.java:150)
        at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:189)
        at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99)
        at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onNext(FluxRetryWhen.java:173)
        at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:160)
        at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.onStateChange(HttpClientConnect.java:389)
        at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:612)
        at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onStateChange(DefaultPooledConnectionProvider.java:195)
        at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnection.onStateChange(DefaultPooledConnectionProvider.java:466)
        at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:613)
        at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:311)
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:432)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1533)
        at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1282)
        at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1329)
        at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508)
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:834)

根据尼古拉的评论,我试图跟随...

RetailTransactionGenericResponseWrapper response =
    webClient.post().uri(url).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
        .headers(headers -> {
            headers.setBearerAuth(token);
        }).accept(APPLICATION_JSON)
        .body(Mono.just(retailTransactionGenericRequest), RetailTransactionGenericResponseWrapper.class)
        .retrieve().bodyToMono(RetailTransactionGenericResponseWrapper.class).block();

像这样

RetailTransactionGenericResponseWrapper response = webClient.post().uri(url).headers(headers -> {
    headers.setBearerAuth(token);
    headers.setContentType(APPLICATION_JSON);
}).contentType(APPLICATION_JSON).accept(APPLICATION_JSON)
    .body(Mono.just(retailTransactionGenericRequest), RetailTransactionGenericResponseWrapper.class).retrieve()
    .bodyToMono(RetailTransactionGenericResponseWrapper.class).block();

我仍然得到相同的异常堆栈

共有1个答案

颜修明
2023-03-14

在WebClient请求中添加以下标题

webClient
   //...
   .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
   //...

如果没有这一点,杰克逊的JSON编解码器就不会被注册为身体提取器候选。如果不指定“内容类型”标题,默认情况下它将是“应用程序/八位字节流”,这是Jackson不支持的。

 类似资料:
  • 我正在Eclipse Enterprise中通过Spring框架而不是Spring Boot编写一个MVC项目。使用Postman,我将向我的方法发送一个json对象: 但是在Eclipse中,我收到了这个错误: 我认为这与我的pom.xml和依赖有关: pom中是否有任何内容。xml我应该更改吗? 其他细节如网络。xml: -servlet.xml

  • 我正在使用JavaSpring框架创建一个时事通讯API。每当我以请求模型的帖子的形式访问API时,我都会得到这个例外组织。springframework。网状物HttpMediaTypeNotSupportedException。 这是我的时事通讯模型 这是我的NewsletterMailerList模型 我给包含类型作为应用程序/json。我是新来做这种事情的。请帮助我为什么会出现这个错误。如

  • 我正在处理一个API的一部分,它需要调用另一个外部API来检索它的一个函数的数据。调用返回HTTP 500错误,描述为“不支持内容类型‘应用程序/八位字节流’。”该调用应返回“application/json”类型。" 我发现这是因为接收到的响应没有在其头中显式指定内容类型,即使其内容的格式为JSON,所以我的API默认假定它是一个八位字节流。 问题是,我不知道如何适应这种情况。即使另一个API没

  • 在SpringJSFWeb应用程序中将Netty客户端处理程序配置为消息接收点,有没有具体的方法? 如果一些独立的Java应用程序充当Netty服务器,我如何接收到SpringJSFWeb应用程序的消息?

  • 我在与Java WS对话时遇到了问题。我使用“WSHTTPBinding”绑定客户端证书进行身份验证,消息编码设置为“text”,.NET framework为4.0。服务器端是Java,我无法控制它。连接是通过Fiddler代理的(这就是我在网上看到请求的方式,比跟踪“System.NET”更加用户友好)。 我得到的例外情况如下: 服务器接受请求的“text”和“mtom”消息编码,响应总是相同