SpringBoot定制JSON響應(yīng)數(shù)據(jù)的實(shí)現(xiàn)
前言
最近在學(xué)習(xí)過(guò)程中發(fā)現(xiàn)了Jackson庫(kù)的@JsonView也可以改變JSON的輸出結(jié)構(gòu),并且可以更加精細(xì)的控制,我平時(shí)一般都會(huì)定義一些DTO去封裝響應(yīng)數(shù)據(jù),使用這種方法可以不用創(chuàng)建DTO,更加優(yōu)雅且高效的方式來(lái)實(shí)現(xiàn)。??
一、如何使用@JsonView這個(gè)注解?
我們可以創(chuàng)建多個(gè)視圖,每個(gè)視圖代表了一組特定的字段。然后,在控制器的方法上,我們可以通過(guò)應(yīng)用這些視圖來(lái)指定應(yīng)該使用哪些字段來(lái)序列化返回的實(shí)體對(duì)象。這種靈活性使得我們能夠輕松應(yīng)對(duì)各種復(fù)雜的業(yè)務(wù)需求。
二、應(yīng)用場(chǎng)景
- 數(shù)據(jù)暴露級(jí)別的控制:
假設(shè)你有一個(gè)用戶實(shí)體(User),包含了一些基本信息(如姓名、年齡)和一些敏感信息(如密碼、郵箱、身份證)。當(dāng)你需要提供一個(gè) API 來(lái)獲取用戶的基本信息時(shí),你可能不希望暴露敏感信息。通過(guò)使用 @JsonView
,你可以定義兩個(gè)視圖:一個(gè)包含基本信息,另一個(gè)包含所有信息。然后,在對(duì)應(yīng)的 API 方法上,你可以使用相應(yīng)的視圖來(lái)控制輸出的數(shù)據(jù)。
根據(jù)用戶角色定制數(shù)據(jù):
在某些情況下,不同的用戶角色可能需要看到不同級(jí)別的數(shù)據(jù)。例如,管理員可能需要看到用戶的所有信息,而普通用戶只能看到基本信息。通過(guò)使用 @JsonView
和 Spring Security,你可以根據(jù)用戶的角色來(lái)動(dòng)態(tài)地決定應(yīng)該暴露哪些數(shù)據(jù)。
API 版本控制:
當(dāng)你的 API 隨時(shí)間發(fā)展并引入新功能時(shí),可能會(huì)有多個(gè)版本的 API。在某些情況下,舊版本的 API 可能不需要包含新引入的字段。通過(guò) @JsonView
,你可以為每個(gè) API 版本定義一個(gè)視圖,并在需要時(shí)切換到相應(yīng)的視圖。
數(shù)據(jù)聚合和拆分:
在某些情況下,你可能需要將多個(gè)實(shí)體的數(shù)據(jù)聚合到一個(gè) JSON 響應(yīng)中,或者將一個(gè)大實(shí)體的數(shù)據(jù)拆分成多個(gè)小實(shí)體。通過(guò)使用 @JsonView
,你可以更輕松地實(shí)現(xiàn)這種數(shù)據(jù)的聚合和拆分。
三、實(shí)戰(zhàn)案例
定義視圖規(guī)則:
public interface UserView { // 展示基本信息 interface Basic {} // 沒(méi)有密碼 interface WithoutPassword extends Basic {} // 展示所有的信息 interface Full extends Basic {} }
定義一個(gè)User,在屬性上面添加@JSsonView注解,并指定視圖
@Data @AllArgsConstructor public class User { @JsonView(UserView.Basic.class) private Long id; @JsonView(UserView.Basic.class) private String username; @JsonView(UserView.Full.class) private String password; @JsonView(UserView.Basic.class) private String nickName; @JsonView(UserView.Basic.class) private String email; @JsonView({UserView.Basic.class,UserView.WithoutPassword.class}) private String phone; }
在控制器方法上指定視圖,一共有兩種方式:注解方式和編程方式。
注解方式
@RestController public class testController { @GetMapping("/user/basic") @JsonView(UserView.Basic.class) public User userBasic(){ User user = new User(1L,"admin","123456","小杰不禿頭","123456@xx.com","188xxxxxxxx"); return user; } @GetMapping("/user/noPassword") @JsonView(UserView.WithoutPassword.class) public User userNoPassword(){ User user = new User(1L,"admin","123456","小杰不禿頭","123456@xx.com","188xxxxxxxx"); return user; } @GetMapping("/user/full") @JsonView(UserView.Full.class) public User userFull(){ User user = new User(1L,"admin","123456","小杰不禿頭","123456@xx.com","188xxxxxxxx"); return user; } }
注意:@JsonView允許一個(gè)視圖類的數(shù)組,但你只能為每個(gè)控制器方法指定一個(gè)。如果需要激活多個(gè)視圖,可以使用復(fù)合接口。
對(duì)上面三個(gè)接口測(cè)試:
// user/basic { "id": 1, "username": "admin", "nickName": "小杰不禿頭", "email": "123456@xx.com", "phone": "188xxxxxxxx" } // user/noPassword { "id": 1, "username": "admin", "nickName": "小杰不禿頭", "email": "123456@xx.com", "phone": "188xxxxxxxx" } // user/full { "id": 1, "username": "admin", "password": "123456", "nickName": "小杰不禿頭", "email": "123456@xx.com", "phone": "188xxxxxxxx" }
編程方式
@RestController public class testController { @GetMapping("/user/basic") //@JsonView(UserView.Basic.class) public MappingJacksonValue userBasic(){ User user = new User(1L,"admin","123456","小杰不禿頭","123456@xx.com","188xxxxxxxx"); MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(user); mappingJacksonValue.setSerializationView(UserView.Basic.class); return mappingJacksonValue; } @GetMapping("/user/noPassword") //@JsonView(UserView.WithoutPassword.class) public MappingJacksonValue userNoPassword(){ User user = new User(1L,"admin","123456","小杰不禿頭","123456@xx.com","188xxxxxxxx"); MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(user); mappingJacksonValue.setSerializationView(UserView.WithoutPassword.class); return mappingJacksonValue; } @GetMapping("/user/full") //@JsonView(UserView.Full.class) public MappingJacksonValue userFull(){ User user = new User(1L,"admin","123456","小杰不禿頭","123456@xx.com","188xxxxxxxx"); MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(user); mappingJacksonValue.setSerializationView(UserView.Full.class); return mappingJacksonValue; } } //測(cè)試結(jié)果跟上面一致
注意:接口返回值必須為MappingJacksonValue。
總結(jié)
@JsonView提供了一種靈活且強(qiáng)大的方式來(lái)控制序列化的 JSON 數(shù)據(jù)。通過(guò)定義視圖和將它們應(yīng)用到屬性和控制器方法上,你可以根據(jù)需要暴露不同級(jí)別的數(shù)據(jù),實(shí)現(xiàn) API 的數(shù)據(jù)定制化。
@JsonView也可以結(jié)合其他的注解一起使用,可以更精細(xì)的控制,比如:@JsonInclude、@JsonIgnore等等。
到此這篇關(guān)于SpringBoot定制JSON響應(yīng)數(shù)據(jù)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot定制響應(yīng)JSON內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談Java序列化和反序列化為何要實(shí)現(xiàn)Serializable接口
這篇文章主要介紹了淺談Java序列化和反序列化為何要實(shí)現(xiàn)Serializable接口,序列化最重要的作用是在傳遞和保存對(duì)象時(shí).保證對(duì)象的完整性和可傳遞性,對(duì)象轉(zhuǎn)換為有序字節(jié)流,以便在網(wǎng)絡(luò)上傳輸或者保存在本地文件中,需要的朋友可以參考下2023-12-12SpringBoot超詳細(xì)講解@Enable*注解和@Import
這篇文章主要介紹了SpringBoot?@Enable*注解和@Import,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Mybatis中Mapper標(biāo)簽總結(jié)大全
這篇文章主要介紹了Mybatis中Mapper標(biāo)簽總結(jié)大全,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06Java對(duì)數(shù)組實(shí)現(xiàn)選擇排序算法的實(shí)例詳解
這篇文章主要介紹了Java對(duì)數(shù)組實(shí)現(xiàn)選擇排序算法的實(shí)例,選擇排序的比較次數(shù)為 O(N^2)而交換數(shù)為O(N),需要的朋友可以參考下2016-04-04Java 3種方法實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換
這篇文章主要介紹了Java 3種方法實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換,幫助大家利用Java處理數(shù)據(jù),感興趣的朋友可以了解下2020-09-09在SpringBoot中整合使用Netty框架的詳細(xì)教程
這篇文章主要介紹了在SpringBoot中整合使用Netty框架的教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06圖解Java中歸并排序算法的原理與實(shí)現(xiàn)
歸并排序是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個(gè)非常典型的應(yīng)用。本文將通過(guò)圖片詳解插入排序的原理及實(shí)現(xiàn),需要的可以參考一下2022-08-08