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 有完美的序列化支持,改造成本极低:
- 修改业务层返回类型:把
Map<String,JSONObject>改为Map<String, Map<String, Long>> - 优化业务层实现,同时修复潜在的赋值隐患:
@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; }
- 同步修改
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适配模块:
- 添加Maven依赖:
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-json-org</artifactId> </dependency>
- 注册模块到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
相关产品推荐
相关产品推荐

