SpringMVC @RequestBody屬性名大寫字母注入失敗的解決
@RequestBody屬性名大寫字母注入失敗
問題描述
我現(xiàn)在有一個接口通過一個實(shí)體去接收一系列的參數(shù),前端傳參為一個JSON字符串,但是當(dāng)我的屬性名以大寫字母開頭,或者第二個字母是大寫字母的時候,我發(fā)現(xiàn)后端接收不到參數(shù)值。
User實(shí)體:
import lombok.Data; @Data public class User{ ?? ?private Long id; ?? ?private Integer pId; ?? ?private String Name; ?? ?//getter,setter由lombok自動生成 ?? ?//setId, setPId, setName ?? ?//getId, getPId, getName }
前端傳參:
{ ? ? "id": 1, ? ? "pId": 70, ? ? "Name": "Jack" }
接口:
?? ?@PostMapping("/add") ?? ?public void add(@RequestBody User user) { ?? ??? ?System.out.println(user.getId()); // 1 ?? ??? ?System.out.println(user.getName());//null ?? ??? ?System.out.println(user.getPId()); // null ?? ?}
問題分析
Name接收不到的原因是JavaBean的規(guī)范不允許出現(xiàn)這樣的屬性名,即首字母為大寫的屬性名(如:Name, URL, SuV…),這種屬性名直接忽略不注入。
解決辦法是:在屬性上面添加注解@JsonProperty(value = “Name”)顯式指定名稱的對應(yīng)關(guān)系;
pId接收不到的原因是JavaBean的規(guī)范說如果第一個字母是小寫,第二個字母大寫的情況(如:pId, sUV…),在生成setter/getter的時候直接在前面加上set/get,比如pId的setter/getter是setpId()/getpId(),所以 pId在注入的時候會尋找setpId()方法,而不是setPId()。
所以解決方案是:1.在屬性上面加注解@JsonProperty(value = “pId”),2.不使用lombok, 手動寫setter -> setpId()
總結(jié):以上兩種類型名稱注入失敗的原因都是因?yàn)镴ackson(Spring使用的JSON處理工具)遵守了JavaBean的規(guī)范導(dǎo)致的,Jackson給的方案就是通過@JsonProperty顯式指定名稱的對應(yīng)關(guān)系。
解決方案
import lombok.Data; import com.fasterxml.jackson.annotation.JsonProperty; @Data public class User{ ?? ?private Long id; ?? ? ?? ?@JsonProperty(value = "pId") ?? ?private Integer pId; ?? ? ?? ?@JsonProperty(value = "Name") ?? ?private String Name; ?? ?//getter,setter由lombok自動生成 ?? ?//setId, setPId, setName ?? ?//getId, getPId, getName }
import com.fasterxml.jackson.annotation.JsonProperty; public class User{ ?? ?private Long id; ?? ?private Integer pId; ?? ? ?? ?@JsonProperty(value = "Name") ?? ?private String Name; ?? ?public void setpId(){ ?? ??? ?//... ?? ?} ?? ?public Integer getpId(){ ?? ??? ?//... ?? ?} ?? ?//other setters,getters ?? ?//... }
@RequestBody時第二個字母大寫,映射不到
記錄一下遇到的一個問題, 賊難受
controller
/** * 添加 * * @param requestNavigationTagVO * @return */ @PostMapping("/add") public JsonData add(@RequestBody RequestNavigationTagVO requestNavigationTagVO) { navigationTagService.add(requestNavigationTagVO); return JsonData.ok(); }
RequestNavigationTagVO
@Builder @AllArgsConstructor @NoArgsConstructor @Data public class RequestNavigationTagVO { /** * id */ private Long id; /** * 所屬導(dǎo)航id */ @NotNull(groups = {AddNavigationTag.class, ModifyNavigationTag.class}, message = "所屬導(dǎo)航id不能為空") private Long pId; /** * 標(biāo)簽名稱 */ @NotBlank(groups = {AddNavigationTag.class, ModifyNavigationTag.class}, message = "標(biāo)簽名稱不能為空") private String name; /** * 排序 */ @NotNull(groups = {AddNavigationTag.class, ModifyNavigationTag.class}, message = "排序不能為空") private Integer sort; }
postman調(diào)接口
{ "pId": 654577072911111, "name":"中餐", "sort":1 }
這是日志拿到的數(shù)據(jù),
可以看到拿不到pId數(shù)據(jù)(p_id的駝峰寫法),
原因: 這里使用的@Data注解(省去了get和set方法)
public Long getPId() { ... } public void setPId(Long PId) { ... }
而javaBean的規(guī)范導(dǎo)致json傳參首字母大寫將永遠(yuǎn)獲取不到
解決辦法
1,不去使用首字目大寫或第二個字母大寫的參數(shù)
2,自己生成get和set方法
3,使用@JsonProperty注解
@JsonProperty("pId") private Long pId;
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
淺析java程序中hibernate的應(yīng)用總結(jié)
hibernate可以理解為是一個中間件它負(fù)責(zé)把java程序的sql語句接收過來發(fā)送到數(shù)據(jù)庫,而數(shù)據(jù)庫返回來的信息hibernate接收之后直接生成一個對象傳給java2013-07-07線程池ThreadPoolExecutor并行處理實(shí)現(xiàn)代碼
這篇文章主要介紹了線程池ThreadPoolExecutor并行處理實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11MyBatis學(xué)習(xí)教程(四)-如何快速解決字段名與實(shí)體類屬性名不相同的沖突問題
我們經(jīng)常會遇到表中的字段名和表對應(yīng)實(shí)體類的屬性名稱不一定都是完全相同的情況,如何解決呢?下面腳本之家小編給大家介紹MyBatis學(xué)習(xí)教程(四)-如何快速解決字段名與實(shí)體類屬性名不相同的沖突問題,一起學(xué)習(xí)吧2016-05-05JPA如何使用nativequery多表關(guān)聯(lián)查詢返回自定義實(shí)體類
這篇文章主要介紹了JPA如何使用nativequery多表關(guān)聯(lián)查詢返回自定義實(shí)體類,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11springcloud中RabbitMQ死信隊列與延遲交換機(jī)實(shí)現(xiàn)方法
死信隊列是消息隊列中非常重要的概念,同時我們需要業(yè)務(wù)場景中都需要延遲發(fā)送的概念,比如12306中的30分鐘后未支付訂單取消,那么本期,我們就來講解死信隊列,以及如何通過延遲交換機(jī)來實(shí)現(xiàn)延遲發(fā)送的需求,感興趣的朋友一起看看吧2022-05-05