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
相关产品推荐
相关产品推荐

