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

Spring使用ResponseEntity返回Map<String,JSONObject>触发序列化异常如何解决

问题解决方案

问题根源

你遇到的报错是因为SpringBoot 默认使用的 Jackson 序列化框架没有内置 org.json.JSONObject 类的序列化支持,无法识别该类的内部结构,所以会抛出 No serializer found 错误;添加 spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false 配置只是跳过了序列化失败的报错,Jackson 无法识别 JSONObject 字段的问题没有解决,最终只会输出空对象。

额外注意点

你提供的 ValidNum 类存在编译错误:构造方法名和类名不一致,需要将构造方法名从 ValidNumber 修正为 ValidNum 才能正常运行。

可选解决方案

方案1:替换 JSONObject 为原生 Map(最推荐,无需额外依赖/配置)

直接用 JDK 原生的 Map 代替 org.json.JSONObject,Jackson 对原生 Map 有完美的序列化支持,改造成本极低:

  1. 修改业务层返回类型:把 Map<String,JSONObject> 改为 Map<String, Map<String, Long>>
  2. 优化业务层实现,同时修复潜在的赋值隐患:
@Override
public Map<String, Map<String, Long>> aggregateData(List<ValidNum> numsData) {
    Map<String, Map<String, Long>> aggData = new HashMap<>();
    for (ValidNum vn : numsData) {
        // 不存在对应item则自动初始化
        Map<String, Long> itemTypesCount = aggData.computeIfAbsent(vn.item, k -> new HashMap<>());
        // 计数累加
        itemTypesCount.put(vn.type, itemTypesCount.getOrDefault(vn.type, 0L) + 1);
    }
    return aggData;
}
  1. 同步修改 AggSuccess 封装类的属性类型:
public class AggSuccess {
    public Map<String, Map<String, Long>> aggSuccess;
    public AggSuccess(Map<String, Map<String, Long>> aggSuccess) {
        this.aggSuccess = aggSuccess;
    }
}

无需修改任何配置,直接运行就能得到预期的JSON结构。

方案2:为Jackson添加org.json序列化模块(保留JSONObject用法)

如果必须要使用 org.json.JSONObject,可以引入Jackson官方的org.json适配模块:

  1. 添加Maven依赖:
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-json-org</artifactId>
</dependency>
  1. 注册模块到Spring的ObjectMapper:
@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JsonOrgModule());
        return objectMapper;
    }
}

配置完成后Jackson就能正确识别并序列化 org.json.JSONObject 对象。

方案3:直接返回JSON字符串(临时快速解决)

你也可以提前把返回结果手动转成JSON字符串,直接返回字符串类型的响应体,同时设置Content-Type为JSON:

@PostMapping(value="/endpoint")
public ResponseEntity<?> aggData(@RequestBody List<ValidNum> nums){
    try {
        Map<String, JSONObject> data = dataService.aggData(nums);
        AggSuccess callSuccessResp = new AggSuccess(data);
        // 手动转JSON字符串
        String jsonStr = new JSONObject(callSuccessResp).toString();
        return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(jsonStr);
    } catch (Error e) {
        AggError callErrorResp = new AggError(e.getMessage());
        return new ResponseEntity<>(callErrorResp, HttpStatus.BAD_REQUEST);
    }
}

这种方案不需要修改现有业务逻辑,但是错误响应的序列化也需要对应适配,适合临时快速修复。

内容的提问来源于stack exchange,提问作者Eunito

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 17:27:05