Spring Boot/Spring REST如何为RESTful响应列表命名?
嘿,这事儿在Spring Boot里其实挺容易搞定的!你想要的就是把原来返回的嵌套列表转换成带自定义命名键的JSON对象对吧?咱们一步步来实现:
核心思路
不要直接返回List<List<...>>,而是用一个顶层DTO(数据传输对象)类来封装你的各个列表,通过Jackson的@JsonProperty注解指定每个列表在JSON中的键名,Spring会自动帮你完成序列化。
步骤1:定义子项的DTO类
先给每个列表里的元素创建对应的实体类,方便Jackson序列化:
市场统计项DTO
public class MarketStat { private String marketname; private int totalmarketcount; // 全参构造函数 public MarketStat(String marketname, int totalmarketcount) { this.marketname = marketname; this.totalmarketcount = totalmarketcount; } // Getter和Setter(如果不用Lombok的话必须写) public String getMarketname() { return marketname; } public void setMarketname(String marketname) { this.marketname = marketname; } public int getTotalmarketcount() { return totalmarketcount; } public void setTotalmarketcount(int totalmarketcount) { this.totalmarketcount = totalmarketcount; } }
处理状态统计项DTO
public class ProcessingMetric { private int discarded; private int received; private int coded; private int completed; // 全参构造函数 public ProcessingMetric(int discarded, int received, int coded, int completed) { this.discarded = discarded; this.received = received; this.coded = coded; this.completed = completed; } // Getter和Setter public int getDiscarded() { return discarded; } public void setDiscarded(int discarded) { this.discarded = discarded; } public int getReceived() { return received; } public void setReceived(int received) { this.received = received; } public int getCoded() { return coded; } public void setCoded(int coded) { this.coded = coded; } public int getCompleted() { return completed; } public void setCompleted(int completed) { this.completed = completed; } }
小技巧:如果不想写繁琐的Getter/Setter,可以用Lombok的
@Data+@AllArgsConstructor注解,记得在项目里引入Lombok依赖哦!
步骤2:定义顶层响应DTO类
这个类用来封装你的所有列表,并用@JsonProperty指定每个列表在JSON中的名称:
import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; public class ApiResponse { // 这里的"MarketStatsList"就是你想要给第一个列表起的名称 @JsonProperty("MarketStatsList") private List<MarketStat> marketStats; // 这里的"ProcessingMetricsList"是第二个列表的名称 @JsonProperty("ProcessingMetricsList") private List<ProcessingMetric> processingMetrics; // 全参构造函数 public ApiResponse(List<MarketStat> marketStats, List<ProcessingMetric> processingMetrics) { this.marketStats = marketStats; this.processingMetrics = processingMetrics; } // Getter和Setter(同样,用Lombok可以省略) public List<MarketStat> getMarketStats() { return marketStats; } public void setMarketStats(List<MarketStat> marketStats) { this.marketStats = marketStats; } public List<ProcessingMetric> getProcessingMetrics() { return processingMetrics; } public void setProcessingMetrics(List<ProcessingMetric> processingMetrics) { this.processingMetrics = processingMetrics; } }
步骤3:修改REST控制器的返回值
把原来返回List<List<Object>>的方法,改成返回我们定义的ApiResponse对象:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @RestController public class StatsController { // 假设你的服务层返回的是List<List<Object>>类型的数据 private List<List<Object>> getRawStatsFromService() { // 模拟你的服务返回数据 return List.of( List.of( Map.of("marketname", "East", "totalmarketcount", 22), Map.of("marketname", "Midwest", "totalmarketcount", 9275), Map.of("marketname", "West", "totalmarketcount", 25) ), List.of( Map.of("discarded", 0, "received", 1268, "coded", 6031, "completed", 5951) ) ); } @GetMapping("/stats") public ApiResponse getStats() { List<List<Object>> rawData = getRawStatsFromService(); // 把第一个子列表转换成List<MarketStat> List<MarketStat> marketStats = rawData.get(0).stream() .map(item -> { Map<String, Object> map = (Map<String, Object>) item; return new MarketStat( (String) map.get("marketname"), ((Number) map.get("totalmarketcount")).intValue() ); }) .collect(Collectors.toList()); // 把第二个子列表转换成List<ProcessingMetric> List<ProcessingMetric> processingMetrics = rawData.get(1).stream() .map(item -> { Map<String, Object> map = (Map<String, Object>) item; return new ProcessingMetric( ((Number) map.get("discarded")).intValue(), ((Number) map.get("received")).intValue(), ((Number) map.get("coded")).intValue(), ((Number) map.get("completed")).intValue() ); }) .collect(Collectors.toList()); // 返回顶层响应对象 return new ApiResponse(marketStats, processingMetrics); } }
最终返回的JSON效果
现在调用/stats接口,就能得到带命名列表的JSON了:
{ "MarketStatsList": [ {"marketname": "East", "totalmarketcount": 22}, {"marketname": "Midwest", "totalmarketcount": 9275}, {"marketname": "West", "totalmarketcount": 25} ], "ProcessingMetricsList": [ {"discarded": 0, "received": 1268, "coded": 6031, "completed": 5951} ] }
如果你的需求是只返回单个命名列表(比如你示例里的EncoderCodedlist),那只需要在顶层DTO里定义一个列表属性就行,逻辑是完全一样的~
内容的提问来源于stack exchange,提问作者sunil
相关产品推荐
相关产品推荐

