Spring Boot 如何返回指定结构JSON?实际返回数组异常排查
问题根因
当前接口返回["0158"]而非预期的{"code":"0158"},核心原因有三点:
- 查询逻辑与返回结构不匹配:两套实现的JPQL语句都只单独选取了
code字段,返回结果本质是字符串集合,序列化框架会直接将这类集合转成JSON数组 - 方法返回类型声明错误:Controller层方法签名直接声明返回
List/Iterable集合类型,序列化逻辑会优先按集合结构输出数组,不会自动包装成键值对对象 - 现有代码存在可直接触发报错的问题:方案2的Repository查询中把实体类的
code字段错写为eacode,字段不匹配会触发运行时错误;同时贴出的实体类定义末尾缺少类闭合的},会触发编译错误。
修正方案
核心调整思路是将返回结构从「字符串集合」改为「携带code属性的键值对对象」,可根据现有实现栈选择对应修正方式:
选择Controller + Service架构的修正步骤
- 调整Service层逻辑
修改JPQL语句返回完整实体,将方法返回值从集合改为单实体查询,最多取1条匹配结果避免返回列表:public SpotCheckModel getSpotChecksteams(String country, String projectId){ TypedQuery<SpotCheckModel> query = (TypedQuery<SpotCheckModel>) entityManager.createQuery( "SELECT e FROM SpotCheckModel e WHERE e.country = :country AND e.project = :projectId"); query.setParameter("country", country); query.setParameter("projectId", projectId); query.setMaxResults(1); List<SpotCheckModel> results = query.getResultList(); return results.isEmpty() ? null : results.get(0); } - 调整Controller层返回类型
去掉集合类型声明,直接返回实体对象即可:@GetMapping(path = "/eareport/spotchecksteams") public ResponseEntity<SpotCheckModel> getSpotChecksteams(@RequestParam("country") String country, @RequestParam("projectId") String projectId){ SpotCheckModel report = dashboardService.getSpotChecksteams(country,projectId); return ResponseEntity.status(HttpStatus.OK).body(report); }提示:如果实体类中存在
htmlcontent、filename等不需要对外暴露的字段,可单独定义仅包含code属性的DTO类作为返回类型,减少冗余数据传输。
选择Controller + Repository架构的修正步骤
- 修正Repository接口定义
修正拼写错误的字段名,将返回类型从Iterable改为单值实体查询:public interface SpotChecksRepository extends CrudRepository<SpotCheckModel, String> { // 修正原查询中字段名eacode的拼写错误,返回完整实体 @Query("SELECT e FROM SpotCheckModel e WHERE e.country = ?1 AND e.project = ?2") Optional<SpotCheckModel> findEntriesByUserId(@Param("country") String country, @Param("projectId") String projectId); } - 调整Controller层逻辑
匹配Repository的返回结构做响应封装:@GetMapping(path = "/eareport/spotchecksteams") public ResponseEntity<SpotCheckModel> getSpotChecksteams(@RequestParam("country") Optional<String> country, @RequestParam("projectId") Optional<String> projectId){ if(country.isPresent() && projectId.isPresent()) { Optional<SpotCheckModel> result = spotChecksRepository.findEntriesByUserId(country.get(), projectId.get()); return result.map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build()); } return ResponseEntity.badRequest().build(); }
按需优化:仅返回code字段的实现
如果不需要返回完整实体对象,可直接在Controller层手动组装Map结构,保留原本仅查询code字段的轻量逻辑:
- Service层保留只查code字段的逻辑,返回单条字符串即可:
public String getSpotCheckCode(String country, String projectId){ TypedQuery<String> query = (TypedQuery<String>) entityManager.createQuery( "SELECT e.code FROM SpotCheckModel e WHERE e.country = :country AND e.project = :projectId"); query.setParameter("country", country); query.setParameter("projectId", projectId); query.setMaxResults(1); List<String> results = query.getResultList(); return results.isEmpty() ? null : results.get(0); } - Controller层组装为Map结构返回:
@GetMapping(path = "/eareport/spotchecksteams") public ResponseEntity<Map<String, String>> getSpotChecksteams(@RequestParam("country") String country, @RequestParam("projectId") String projectId){ String code = dashboardService.getSpotCheckCode(country, projectId); if(code == null) { return ResponseEntity.notFound().build(); } Map<String, String> result = new HashMap<>(); result.put("code", code); return ResponseEntity.ok(result); }
内容的提问来源于stack exchange,提问作者arriff
相关产品推荐
相关产品推荐

