You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rest Assured反序列化时响应包装类字段为空问题排查

问题:Rest Assured反序列化API响应后DTO字段全为null

在Rest Assured中调用API并尝试将响应反序列化到InCalendarDateResponseWrapper DTO时,所有字段均返回null,但控制台通过log().all()能正常打印完整响应内容。

相关代码片段

请求代码

ValidatableResponse response = given().header("Authorization", token).header("Content-type", "application/json")
                .when().log().all().pathParam("CalendarId", testCaseBean.getCalendarId().toString()).urlEncodingEnabled(false)
                .queryParam("from", testCaseBean.getStartDate()).queryParam("to", testCaseBean.getEndDate())
                .queryParam("monthEnd", testCaseBean.getMonthEndBusinessDay())
                .get(EndPoint.GET_CALENDAR_DETAILS_BY_MULTIPLE_CALENDAR_CODE).then().log().all();

InCalendarDateResponseWrapper actualRIOutput = CommonUtils.getJSONMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .readValue(response.extract().asString(), InCalendarDateResponseWrapper.class);
String t=actualRIOutput.getCalendarId(); // t为null

DTO类代码

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.time.LocalDate;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class InCalendarDateResponseWrapper {
    private String calendarId;
    private LocalDate calDat;
    private LocalDate prevBus;
    private LocalDate nextBus;
    private Boolean bus;
    private Boolean monthEnd;
}

API响应结构

{
    "EU": [
        {
            "calendarId": "EU",
            "calDat": "2022-11-01",
            "prevBus": "2022-10-31",
            "nextBus": "2022-11-02",
            "bus": true,
            "monthEnd": false
        }
    ],
    "AU": [
        {
            "calendarId": "AU",
            "calDat": "2022-11-01",
            "prevBus": "2022-10-31",
            "nextBus": "2022-11-02",
            "bus": true,
            "monthEnd": false
        }
    ]
}

ObjectMapper工具类代码

public static ObjectMapper getJSONMapper() {
    objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.registerModule(new JavaTimeModule());
    return objectMapper;
}

问题原因

核心问题是API响应结构与DTO不匹配:

  • API返回的是一个键为日历代码(如EU、AU),值为InCalendarDateResponseWrapper对象数组的Map结构;
  • 而代码中直接用InCalendarDateResponseWrapper.class进行反序列化,Jackson无法在根层级找到与DTO字段匹配的key,再加上开启了FAIL_ON_UNKNOWN_PROPERTIES=false,会忽略不匹配的字段,最终导致DTO所有字段为空。

解决方案

方案1:接收完整的响应结构

将反序列化目标改为Map<String, List<InCalendarDateResponseWrapper>>,匹配API的Map结构:

Map<String, List<InCalendarDateResponseWrapper>> actualResponse = CommonUtils.getJSONMapper()
        .readValue(response.extract().asString(), new TypeReference<Map<String, List<InCalendarDateResponseWrapper>>>() {});

// 获取EU对应的日历数据
List<InCalendarDateResponseWrapper> euCalendars = actualResponse.get("EU");
if (!euCalendars.isEmpty()) {
    String calendarId = euCalendars.get(0).getCalendarId(); // 此时calendarId为"EU"
}

方案2:提取单个日历节点反序列化

如果只需要某一个日历的数据,可以直接从响应中提取对应节点再反序列化:

// 方式1:用Rest Assured的path方法直接提取
InCalendarDateResponseWrapper euCalendar = response.extract().path("EU[0]");

// 方式2:用Jackson解析JsonNode后提取
JsonNode rootNode = CommonUtils.getJSONMapper().readTree(response.extract().asString());
JsonNode euNode = rootNode.get("EU").get(0);
InCalendarDateResponseWrapper euCalendar = CommonUtils.getJSONMapper().treeToValue(euNode, InCalendarDateResponseWrapper.class);

调试建议

临时关闭FAIL_ON_UNKNOWN_PROPERTIES=false配置,Jackson会在结构不匹配时抛出异常,帮助快速定位问题:

InCalendarDateResponseWrapper actualRIOutput = CommonUtils.getJSONMapper()
        //.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .readValue(response.extract().asString(), InCalendarDateResponseWrapper.class);

内容的提问来源于stack exchange,提问作者Pratik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:01:37