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

如何从OMDb接口返回的HashMap中提取ArrayList类型的Search数据?

解决OMDb接口调用的Search字段类型转换异常

你的代码里有三个核心问题导致了ArrayList cannot be cast to String的异常:

  1. 错误声明了Map<String, String>泛型 —— OMDb返回的Search是数组类型,不是字符串,强转必然报错。
  2. 直接把ResponseSpec传给ObjectMapper —— ResponseSpec是响应规范对象,不是JSON数据源,不能直接用来反序列化。
  3. bodyToMono(String.class).map()代码不完整 —— map方法必须传入处理逻辑,而且这里完全没必要手动处理JSON。

下面是两种可行的解决方案:


方案一:用实体类直接反序列化(推荐)

这是Spring WebClient的最佳实践,避免手动解析JSON的繁琐和错误。

1. 创建匹配返回结构的实体类

// 对应OMDb的顶层响应
public class OmdbResponse {
    private List<Movie> Search;
    private String totalResults;
    private String Response;

    // 自动生成Getter、Setter方法
}

// 电影实体类,对应Search里的每个元素
public class Movie {
    private String Title;
    private String Year;
    private String imdbID;
    private String Type;
    private String Poster;

    // 自动生成Getter、Setter方法
}

2. 优化WebClient调用代码

WebClient webClient = WebClient.create();
String searchKeyword = "batman";
String apiKey = "你的OMDb密钥"; // 替换成实际API Key

// 用URI占位符构建请求,避免字符串拼接的编码问题
OmdbResponse omdbResponse = webClient.get()
        .uri("http://www.omdbapi.com/?apikey={apiKey}&s={search}&type=movie&page=1", apiKey, searchKeyword)
        .retrieve()
        .bodyToMono(OmdbResponse.class) // 直接反序列化为实体类
        .block(); // 同步场景用block,异步场景改用subscribe

// 处理返回的电影列表
if (omdbResponse != null && "True".equals(omdbResponse.getResponse())) {
    List<Movie> movieList = omdbResponse.getSearch();
    for (Movie movie : movieList) {
        // 逐个处理电影数据,比如打印标题
        System.out.println("电影:" + movie.getTitle() + ",年份:" + movie.getYear());
    }
}

方案二:手动解析JSON(不推荐,仅作参考)

如果一定要用ObjectMapper手动处理,需要修正泛型和数据源:

WebClient webClient = WebClient.create();
String searchKeyword = "batman";
String apiKey = "你的OMDb密钥";

// 先获取完整的响应体字符串
String responseBody = webClient.get()
        .uri("http://www.omdbapi.com/?apikey={apiKey}&s={search}&type=movie&page=1", apiKey, searchKeyword)
        .retrieve()
        .bodyToMono(String.class)
        .block();

ObjectMapper objectMapper = new ObjectMapper();
// 用Map<String, Object>接收,因为值可能是字符串或数组
Map<String, Object> responseMap = objectMapper.readValue(responseBody, Map.class);

// 提取Search字段并强制转换为List
List<Map<String, String>> searchRawList = (List<Map<String, String>>) responseMap.get("Search");

// 转换为Movie对象列表
List<Movie> movieList = new ArrayList<>();
for (Map<String, String> movieMap : searchRawList) {
    Movie movie = objectMapper.convertValue(movieMap, Movie.class);
    movieList.add(movie);
}

// 后续处理电影数据
for (Movie movie : movieList) {
    System.out.println(movie.getTitle());
}

关键提醒

  • 永远不要用Map<String, String>接收包含数组的JSON,泛型必须和实际JSON结构匹配。
  • WebClient的bodyToMono可以直接处理JSON反序列化,尽量避免手动解析,减少出错概率。
  • 构建URI时用占位符,避免直接拼接字符串导致的编码错误(比如搜索关键词含特殊字符时)。

内容的提问来源于stack exchange,提问作者An Nguyen Thanh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 11:35:32