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

Spring Boot 如何返回指定结构JSON?实际返回数组异常排查

问题根因

当前接口返回["0158"]而非预期的{"code":"0158"},核心原因有三点:

  • 查询逻辑与返回结构不匹配:两套实现的JPQL语句都只单独选取了code字段,返回结果本质是字符串集合,序列化框架会直接将这类集合转成JSON数组
  • 方法返回类型声明错误:Controller层方法签名直接声明返回List/Iterable集合类型,序列化逻辑会优先按集合结构输出数组,不会自动包装成键值对对象
  • 现有代码存在可直接触发报错的问题:方案2的Repository查询中把实体类的code字段错写为eacode,字段不匹配会触发运行时错误;同时贴出的实体类定义末尾缺少类闭合的},会触发编译错误。
修正方案

核心调整思路是将返回结构从「字符串集合」改为「携带code属性的键值对对象」,可根据现有实现栈选择对应修正方式:

选择Controller + Service架构的修正步骤

  1. 调整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);
    }
    
  2. 调整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架构的修正步骤

  1. 修正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);
    }
    
  2. 调整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字段的轻量逻辑:

  1. 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);
    }
    
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 01:15:06