如何在Spring Boot中使用WebClient获取JSON并映射为自定义对象集合
实现方案步骤
第一步:引入必要依赖
确保项目引入WebClient和Jackson相关依赖,Spring Boot项目直接添加webflux起步依赖即可,内置默认包含Jackson序列化组件:
<!-- Maven 依赖示例 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
第二步:数据映射实现
由于返回JSON中symbols是键值对对象而非数组,无法直接反序列化为List集合,推荐两种实现方案:
方案1:通过中间DTO转换(逻辑清晰,无需自定义序列化规则)
- 先定义和返回JSON结构完全匹配的中间传输对象
public class CurrencyRawResponse { private Boolean success; private Map<String, String> symbols; // 自行补充getter、setter方法 }
- WebClient调用后手动转换为目标实体类
import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import java.util.List; import java.util.stream.Collectors; public class CurrencyService { private final WebClient webClient; // 推荐通过Spring注入WebClient.Builder初始化 public CurrencyService(WebClient.Builder webClientBuilder) { this.webClient = webClientBuilder.baseUrl("替换为你的接口根地址").build(); } public Mono<Currencies> getCurrencyList() { return webClient.get() .uri("替换为你的接口请求路径") .retrieve() .bodyToMono(CurrencyRawResponse.class) .map(rawResponse -> { Currencies result = new Currencies(); // 注意你原定义的success是String类型,接口返回是布尔值,此处做类型转换 result.success = String.valueOf(rawResponse.getSuccess()); // 将symbols的Map转为目标集合 List<ExternalCurrency> currencyList = rawResponse.getSymbols().entrySet().stream() .map(entry -> { ExternalCurrency currency = new ExternalCurrency(); currency.shortCode = entry.getKey(); currency.name = entry.getValue(); return currency; }).collect(Collectors.toList()); result.currencyList = currencyList; return result; }); } }
方案2:自定义反序列化器直接映射
如果不想额外定义中间DTO,可以通过Jackson自定义反序列化规则直接映射到目标类:
- 编写自定义反序列化器
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class CurrenciesDeserializer extends StdDeserializer<Currencies> { public CurrenciesDeserializer() { super(Currencies.class); } @Override public Currencies deserialize(JsonParser parser, DeserializationContext context) throws IOException { JsonNode rootNode = parser.getCodec().readTree(parser); Currencies currencies = new Currencies(); currencies.success = rootNode.get("success").asText(); List<ExternalCurrency> list = new ArrayList<>(); // 遍历symbols节点的所有键值对 rootNode.get("symbols").fields().forEachRemaining(entry -> { ExternalCurrency currency = new ExternalCurrency(); currency.shortCode = entry.getKey(); currency.name = entry.getValue().asText(); list.add(currency); }); currencies.currencyList = list; return currencies; } }
- 给Currencies类绑定反序列化器
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @JsonDeserialize(using = CurrenciesDeserializer.class) public class Currencies { public String success; public List<ExternalCurrency> currencyList; }
- 直接调用WebClient反序列化即可
public Mono<Currencies> getCurrencyList() { return webClient.get() .uri("替换为你的接口请求路径") .retrieve() .bodyToMono(Currencies.class); }
补充说明
- 如果需要同步获取结果,在返回的Mono对象后调用
.block()方法即可,注意不要在非阻塞线程池内调用block方法 - 建议将Currencies类的success字段改为Boolean类型,和接口返回类型匹配,避免额外的类型转换逻辑
内容的提问来源于stack exchange,提问作者Fatih AKSOY
相关产品推荐
相关产品推荐

