GET请求响应反序列化为自定义POJO后字段值为null的问题排查
问题描述
我尝试将GET请求的响应存储到自定义的Bean类中,但发现POJO内声明的变量值为null。以下是相关代码及响应:
GET请求代码
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(); IndexCalendarDateResponseBean actualRIOutput = CommonUtils.getJSONMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .readValue(response.extract().asString(), IndexCalendarDateResponseBean.class);
IndexCalendarDateResponseBean类代码
package com.tar.indexes.bean; import java.time.LocalDate; import java.util.List; import com.tar.indexes.marketdata.api.dto.IndexCalendarDateResponseWrapper; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class IndexCalendarDateResponseBean { List<IndexCalendarDateResponseWrapper> calendarId; }
InCalendarDateResponseWrapper类代码
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 } ] }
执行以下调试代码时:
String t = actualRIOutput.getCalendarId().get(0).getCalendarId(); System.out.println(t);
得到的t值为null而非预期的EU,请问问题出在哪里?
问题原因及解决方案
核心问题:POJO结构与API响应格式不匹配
你的API响应是以动态日历ID(如EU、AU)为键的JSON对象,每个键对应一个InCalendarDateResponseWrapper对象的数组;但你定义的IndexCalendarDateResponseBean用了List<IndexCalendarDateResponseWrapper> calendarId,这个结构和响应完全不匹配,Jackson无法将JSON对象映射到List类型的字段上,所以calendarId字段会被赋值为null,后续调用get(0)自然会出现问题(甚至可能抛出空指针异常)。
解决方案
修改POJO结构使其匹配响应格式,有两种可选方案:
方案1:修改IndexCalendarDateResponseBean为Map结构
将IndexCalendarDateResponseBean改为:
package com.tar.indexes.bean; import java.util.List; import java.util.Map; import com.tar.indexes.marketdata.api.dto.InCalendarDateResponseWrapper; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class IndexCalendarDateResponseBean { // 键为日历ID(如EU、AU),值为对应日期列表 private Map<String, List<InCalendarDateResponseWrapper>> calendarData; }
反序列化后通过键获取对应数据:
// 获取EU对应的日期列表 List<InCalendarDateResponseWrapper> euCalendar = actualRIOutput.getCalendarData().get("EU"); if(euCalendar != null && !euCalendar.isEmpty()){ String calendarId = euCalendar.get(0).getCalendarId(); System.out.println(calendarId); // 输出EU }
方案2:直接反序列化为Map类型
如果不需要额外的Bean类,可直接将响应字符串反序列化为Map:
import com.fasterxml.jackson.core.type.TypeReference; // 省略其他代码 Map<String, List<InCalendarDateResponseWrapper>> calendarMap = CommonUtils.getJSONMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .readValue(response.extract().asString(), new TypeReference<Map<String, List<InCalendarDateResponseWrapper>>>() {}); // 获取EU对应的第一个元素的calendarId String t = calendarMap.get("EU").get(0).getCalendarId(); System.out.println(t); // 输出EU
额外注意点
- 代码中引用的
IndexCalendarDateResponseWrapper和实际类名InCalendarDateResponseWrapper不一致,需要统一类名,避免编译或运行错误。 - 确保Jackson支持
LocalDate反序列化,需添加jackson-datatype-jsr310依赖,并在ObjectMapper中注册JavaTimeModule:
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; // 省略其他代码 CommonUtils.getJSONMapper() .registerModule(new JavaTimeModule()) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
内容的提问来源于stack exchange,提问作者Pratik
相关产品推荐
相关产品推荐

