调用电影API时出现空指针及JSON反序列化异常求助
问题分析与解决:Spring Boot调用TMDB API遇到的两个问题
问题1:NullPointerException(result()返回null)
原因
API返回的是数组类型的results字段,但你的MovieResponse定义的是单个Results对象的result字段——字段名(单数vs复数)、类型(单个对象vs数组)都不匹配,导致Jackson无法正确反序列化,result()自然返回null,调用其方法就触发了空指针异常。
解决步骤
- 修改
MovieResponse的字段定义:把result改成results,类型从Results改为List<Results>,同时保留@JsonIgnoreProperties(ignoreUnknown = true)以忽略API返回的额外字段(如total_pages、total_results):
@JsonIgnoreProperties(ignoreUnknown = true) public record MovieResponse ( Page page, List<Results> results) { }
- 调整
saveMovieEntity方法:因为现在是数组,需要选择其中一个元素(比如第一个)构建MovieEntity,同时增加空判断避免再次触发空指针:
private MovieEntity saveMovieEntity(String title, MovieResponse movieResponse){ if (movieResponse.results() == null || movieResponse.results().isEmpty()) { throw new RuntimeException("未找到匹配的电影数据"); } Results firstResult = movieResponse.results().get(0); MovieEntity movieEntity = new MovieEntity( firstResult.original_language(), firstResult.original_title(), firstResult.release_date(), firstResult.overview(), firstResult.popularity(), movieResponse.page().getPage() ); return movieRepository.save(movieEntity); }
问题2:UnrecognizedPropertyException(无法识别"results"字段)
原因
移除@JsonIgnoreProperties(ignoreUnknown = true)后,Jackson会严格校验所有JSON字段:一方面API返回的results字段和你定义的result字段名不匹配,另一方面API返回的total_pages、total_results等字段在MovieResponse中未定义,因此抛出异常。
解决步骤
- 按问题1的要求修正
MovieResponse的字段名和类型,让字段名results与API返回一致 - 保留
@JsonIgnoreProperties(ignoreUnknown = true),或者显式指定要忽略的字段(如@JsonIgnoreProperties({"total_pages", "total_results"})),处理API返回的额外字段
额外优化建议
- 把
Page类改为record,简化代码:
public record Page(Integer page) {}
- 直接用
restTemplate.getForObject完成反序列化,省去手动调用objectMapper的步骤:
private MovieEntity getMovieFromTheMovieApi(String title){ MovieResponse movieResponse = restTemplate.getForObject(API_URL + title, MovieResponse.class); if (movieResponse == null) { throw new RuntimeException("API请求失败"); } return saveMovieEntity(title , movieResponse); }
- 将
Results中的集合字段类型从ArrayList改为List,符合面向接口编程规范:
public record Results( boolean adult, String backdrop_path, Object belongs_to_collection, Integer budget, List<Object> genres, String homepage, Integer id, String imdb_id, String original_language, String original_title, String overview, Number popularity, String poster_path, List<Object> production_companies, List<Object> production_countries, String release_date, Integer revenue, Integer runtime, List<Object> spoken_languages, String status, String tagline, String title, boolean video, Number vote_average, Integer vote_count ) {}
内容的提问来源于stack exchange,提问作者Eray Nacarlı
相关产品推荐
相关产品推荐

