今天在封裝第三方應用的開放接口,寫了很多返回值的類,這些類很多都是結構相似只是個別字段名稱不一樣。為了單獨的字段就要復制一個改改不勝其煩,而且起名是最頭疼的事情。就像下面這兩個:
- @EqualsAndHashCode(callSuper = true)
- @Data
- public class SimpleUserResponse extends WeComResponse {
- private List<SimpleUser> userlist;
- }
- @EqualsAndHashCode(callSuper = true)
- @Data
- public class UserDetailResponse extends WeComResponse {
- private List<UserDetail> userlist;
- }
是不是差不多?于是就利用泛型將它們合并了:
- @EqualsAndHashCode(callSuper = true)
- @Data
- public class UserResponse<T> extends WeComResponse {
- private List<T> userlist;
- }
這樣通過UserResponse
- @EqualsAndHashCode(callSuper = true)
- @Data
- public class QrCodeResponse extends WeComResponse {
- private String qrcode;
- }
這個結構其實也差不多啊,如果把UserResponse
- @EqualsAndHashCode(callSuper = true)
- @Data
- public class OjbectResponse<T> extends WeComResponse {
- private T userlist;
- }
似乎OjbectResponse
如果是類型轉換
Bean類型轉換的話,用Mapstruct就能解決這個問題,最終我們把屬性名稱定義為data:
- @Mapping(target = "data", source = "qrcode")
- @Mapping(target = "data", source = "userlist")
通過上面的兩個注解映射編寫兩個轉換接口就解決了。關于Mapstruct可以看我相關的講解文章。
如果是反序列化
Jackson提供了一個別名注解@JsonAlias,可以讓字段屬性名稱接受更多的別名。就像這樣:
- @EqualsAndHashCode(callSuper = true)
- @Data
- public class OjbectResponse<T> extends WeComResponse {
- @JsonAlias({"qrcode","userlist"})
- private T data;
- }
那么下面這個json能映射到OjbectResponse
- {
- "qrcode":"https://felord.cn/myqr.png"
- }
這個會映射到OjbectResponse
- {
- "userlist":[{"username":"felord.cn"},{"username":"felordcn"},{"username":"felord"}]
- }
到這里可能大家會有疑問:Jackson是如何處理泛型問題的?
如何獲取泛型的Class類型
通過直接手段是無法獲取泛型的Class類型的,不過我們可以獲取到泛型的抽象定義java.lang.reflect.ParameterizedType,直接使用ParameterizedType會不太方便。所以在Jackson中可以通過TypeReference
- ObjectMapper objectMapper = new ObjectMapper();
- String json = "{\"qrcode\":\"https://felord.cn/myqr.png\"}";
- OjbectResponse<String> obj = objectMapper.readValue(json,new TypeReference<OjbectResponse<String>>(){});
其實對應的Spring也提供了類似的工具類org.springframework.core.ParameterizedTypeReference
原文鏈接:https://mp.weixin.qq.com/s/XQT8Qrx9yQdjjKNHGsfePQ