Java Jackson如何反序列化字段名动态变化的JSON为Java类
问题排查及解决
1. 日期格式化错误导致请求参数异常
你当前使用的SimpleDateFormat格式为yyyy-mm-dd,其中小写mm代表分钟,实际需要的月份应该用大写MM,错误的日期格式会导致请求的date参数不符合接口要求,返回的数据不符合预期。
修改代码:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
2. @JsonAnySetter使用错误,无法映射顶级动态键
你当前定义的EventsGetCategory类,直接在Map字段上加@JsonAnySetter无法实现将所有顶级动态日期键映射到details字段的效果,有两种修复方案:
方案一:直接使用Map接收(最简方案,无需自定义包装类)
直接把RestTemplate的返回类型改为Map<String, List<EventDetails>>,Jackson可以直接把动态键的JSON反序列化为对应Map:
private Map<String, List<EventDetails>> getEventFromAPI(Date startdate, Date enddate) { RestTemplate restTemplate = new RestTemplate(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); ResponseEntity<Map<String, List<EventDetails>>> response = restTemplate.getForEntity( matomoUrl + "index.php?module=API&label=OnlineGallery&method=Events.getCategory&secondaryDimension=eventAction&idSite=1&period=day&date=" + dateFormat.format(startdate) + "," + dateFormat.format(enddate) + "&format=JSON&filter_limit=-1" + "&token_auth=" + tokenAuth, new ParameterizedTypeReference<Map<String, List<EventDetails>>>() {}); return response.getBody(); }
注意:这里需要用
ParameterizedTypeReference传递泛型类型,避免Java泛型擦除导致反序列化失败。
方案二:修正EventsGetCategory类的注解配置
如果一定要保留EventsGetCategory包装类,需要修改类配置,@JsonAnySetter如果用在字段上需要Jackson 2.8+版本支持,也可以显式写set方法加注解:
@Data public class EventsGetCategory { private Map<String, List<EventDetails>> details = new HashMap<>(); @JsonAnySetter public void addDetail(String dateKey, List<EventDetails> eventList) { details.put(dateKey, eventList); } // 若需要序列化可以加这个注解,不需要序列化可以省略 @JsonAnyGetter public Map<String, List<EventDetails>> getDetails() { return details; } }
3. 可选:保证下划线字段正常映射
如果后续你把Java字段改为驼峰命名(比如把nb_uniq_visitors改为nbUniqVisitors),需要在字段上加@JsonProperty("nb_uniq_visitors")注解,或者全局配置Jackson的命名策略为PropertyNamingStrategy.SNAKE_CASE,避免字段映射失败。你当前的Java字段名和JSON键完全一致,不需要额外配置。
内容的提问来源于stack exchange,提问作者Tanja298
相关产品推荐
相关产品推荐

