首页 > 解决方案 > WebClient 无法正确解析 JSON 响应

问题描述

我希望有人可以帮助我几天我一直在努力解决这个问题。

我想用 WebClient 创建一个 Rest Client 来从 API 检索响应。所以我创建了我的 Spring 项目,添加了 webflux、lombok 和 h2。我还创建了一个 DTO 类“CashAccount”和以下方法:

public String retrieveAccountById(String accountId) {
    return webClient.get()
            .uri(GET_ACCOUNT_BY_ID_V4, accountId)
            .header("Auth-Schema", AUTH_SCHEMA)
            .header("apikey", API_KEY)
            .accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .onStatus(HttpStatus::is4xxClientError, response -> {
                System.out.println("4xx error");
                return Mono.error(new RuntimeException("4xx"));
              })
              .onStatus(HttpStatus::is5xxServerError, response -> {
                System.out.println("5xx error");
                return Mono.error(new RuntimeException("5xx"));
              })
            .bodyToMono(String.class) // .bodyToMono(CashAccount.class)
            .block();
}

当我使用“.bodyToMono(String.class)”时,一切正常,我收到了结果:

    2:50:27.548 [reactor-http-nio-2] DEBUG org.springframework.core.codec.StringDecoder - [43ed0ff3] [6449a63b-1, L:/192.168.1.72:60756 - R:sandbox.io/210.278.152.97:443] Decoded "{
  "status": "OK",
  "error": [],
  "payload": {"accountId":"80377145","iban":"IT10L01234567890 (truncated)...

相反,当我使用“.bodyToMono(CashAccount.class)”时,我收到一个所有变量都为空的对象:

23:17:31.236 [reactor-http-nio-2] DEBUG org.springframework.http.codec.json.Jackson2JsonDecoder - [43ed0ff3] [77c463f4-1, L:/192.168.1.72:62306 - R:sandbox.io/210.278.152.97:443] Decoded [CashAccount(accountId=null, iban=null, abiCode=null, cabCode=null, countryCode=null, internationalCi (truncated)...]

这是我的 DTO 课程:

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class CashAccount {

        private String accountId; 
        private String iban; 
        ...
    }

我究竟做错了什么?

标签: javaspringspring-webfluxlombokdto

解决方案


问题是您试图仅将有效负载对象映射到 CashAccount。您的 dto 中还应该有一个状态和错误数组。

关于您的 json 响应:

添加缺少字段的 dto

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResponseDto {
  private String status;
  private List<String> error;
  private CashAccount payload;
}

然后改变 .bodyToMono(ResponseDto.class)

我建议您使用 @JsonTest 测试您的映射

@JsonTest
class TestMarshalling {

@Autowired ObjectMapper mapper;

@Test
@SneakyThrows
void testmarshalling() {
  String response =
    "{\n"
        + "  \"status\": \"OK\",\n"
        + "  \"error\": [],\n"
        + "  \"payload\": 
     {\"accountId\":\"80377145\",\"iban\":\"IT10L01234567890\"}}";

  var cashAccount = mapper.readValue(response , ResponseDto.class);
  Assertions.assertNotNull(cashAccount.getPayload());
  Assertions.assertNotNull(cashAccount.getPayload().getAccountId());
  Assertions.assertNotNull(cashAccount.getPayload().getIban());
  }
}

推荐阅读