Spring Boot POST请求报错:Map未填充引发NumberFormatException
问题原因分析
你遇到的核心问题是用错了注解来接收POST请求体,才导致newTransaction Map始终为空,进而触发了NumberFormatException。
为什么Map是空的?
你在Controller方法里用了@PathVariable Map<String, String> newTransaction,但@PathVariable的作用是从URL路径里提取参数(比如/transactions/{id}/{type}这种路径中的变量),根本不是用来读取POST请求体里的JSON数据的。当你用Postman发JSON请求体时,Spring完全不会把请求体内容填充到这个Map里,它自然是空的,调用newTransaction.get("id")返回null,转int时就抛出了异常。
为什么单元测试能正常跑?
你的单元测试是直接调用Controller方法并传入手动构建的Map,绕开了HTTP请求的解析流程,Spring不需要处理请求体和注解的映射关系,所以方法能正常接收Map参数并执行逻辑。
解决方案
要正确接收POST请求体里的JSON数据,你需要做以下修改:
1. 修正Controller方法的参数注解
把@PathVariable换成@RequestBody,更推荐你创建专门的DTO类来接收请求参数(比用Map更规范、易维护):
步骤1:创建TransactionRequest DTO类
public class TransactionRequest { private String id; private String type; private String numOfShares; private String pricePerShare; private String ticker; private String commission; private String comments; // 生成所有属性的getter和setter方法 public String getId() { return id; } public void setId(String id) { this.id = id; } // 其他属性的getter/setter同理补充... }
步骤2:修改Controller方法
@PostMapping("/transactions") public Transaction addTransaction(@RequestBody TransactionRequest request) { int transID = Integer.parseInt(request.getId()); TransactionType transType; if("BUY".equals(request.getType().toUpperCase())){ transType = TransactionType.BUY; } else if("SELL".equals(request.getType().toUpperCase())){ transType = TransactionType.SELL; } else { transType = null; } // 其他逻辑:解析request中的其他参数,比如将numOfShares转为数值类型等 // ...MORE LOGIC HERE... return transMD.recordNewTransaction(new Transaction(transID, transType, transNumOfShares, transPricePerShare, transTickerSymbol, transCommission, transComments)); }
如果坚持要用Map接收(不推荐,缺乏类型校验和可读性),直接替换注解即可:
@PostMapping("/transactions") public Transaction addTransaction(@RequestBody Map<String, String> newTransaction) { // 原逻辑不变,此时newTransaction会被Spring自动填充请求体的JSON数据 }
2. 确保Postman请求配置正确
发送请求时注意:
- 请求方法选
POST - 请求URL填
/transactions - 在
Body标签下选择raw,格式选JSON - 粘贴你的JSON请求体:
{ "id" : "6", "type" : "BUY", "numOfShares" : "5000", "pricePerShare" : "45.23", "ticker" : "XYZ", "commission" : "4.95", "comments" : "Mgmt Change" }
额外建议
- 尽量用DTO类接收请求参数,这样可以利用Spring的自动类型转换(比如把
id直接定义为Integer,省去手动parseInt),还能添加@NotNull这类参数校验注解,提前拦截非法请求。 - 处理
TransactionType时可以简化代码:
try { transType = TransactionType.valueOf(request.getType().toUpperCase()); } catch (IllegalArgumentException e) { transType = null; }
内容的提问来源于stack exchange,提问作者user9526185
相关产品推荐
相关产品推荐

