在構(gòu)建一個基于JSON的API的時候, 往往我們還會需要添加一些額外的字段, 形成類似于 數(shù)據(jù)主體/額外信息 結(jié)構(gòu)的數(shù)據(jù), 如:
{
"mainContent": { // 數(shù)據(jù)主體
"name": "小明",
"age": 11
},
"external": { // 額外信息
"errorMsg": "OK",
"errorCode": "0"
}
}
方法1 建一個帶泛型的 pojo , 將數(shù)據(jù)塞進去, 然后JSON化輸出
這樣的類可以是:
public class BizDto<T> {
public BizDto() {
// 為了方便, 設(shè)置默認值
External external = new External();
external.setErrorCode("0");
external.setErrorMsg("OK");
}
private T mainContent;
private External external;
public T getMainContent() {
return mainContent;
}
public void setMainContent(T mainContent) {
this.mainContent = mainContent;
}
public External getExternal() {
return external;
}
public void setExternal(External external) {
this.external = external;
}
public class External{
private String errorMsg;
private String errorCode;
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
}
}
然后所有的 restfull api 都用這個 pojo 封裝一下再輸出
方法2 干預(yù) spring json 序列化的過程
使用這個辦法的好處是 controller 方法的返回值不需要做任何改變, 可以直接輸出數(shù)據(jù)主體
先自定義HttpMessageConverter
來實現(xiàn)自定義的 java轉(zhuǎn)換過程 (from java/ to java)
然后呢 通過覆蓋 spring 默認的 HttpMessageConverters, 或者將自己的 converter 加上去, 辦法是聲明一個 bean
@Bean
public HttpMessageConverters additionalConverters() {
return new HttpMessageConverters(new TheCustomConverter());
}
HttpMessageConverters 有3個構(gòu)造方法
HttpMessageConverters(HttpMessageConverter<?>... additionalConverters)
HttpMessageConverters(Collection<HttpMessageConverter<?>> additionalConverters)
HttpMessageConverters(boolean addDefaultConverters, Collection<HttpMessageConverter<?>> converters)
前兩個是給spring 默認處理列表中添加一個新的 converter, 第三個是覆蓋掉默認的 converters, 只使用自己定義的
使用這個方法還需要考慮一種情況, 就是出錯了, 要怎么輸出錯誤信息到前端
思路是使用@ControllerAdvice
+ 自定義 runtime Exception
遇到錯誤, 直接 throw new CustomeRuntimeException("errorcode","errormsg", ex)
交給框架去處理
小尾巴:
既然 spring 默認帶了 jackson 作為 json 的序列化工具, 有沒有人想過直接使用這個工具來序列化java對象呢, 多數(shù)時候我們都是再用一個第三方j(luò)ar包比如著名的 fastJSON. 但再添加一個第三方工具帶來的麻煩是 json 序列化時配置的不統(tǒng)一了
比如說 jackson 默認會將 Date 對象格式化成 utc 格式, 而fastJson會將日期輸出成 毫秒 時間戳
有一個全局統(tǒng)一的配置, 可以避免在輸出時每次都控制一下格式化, 而且很容易遺漏
辦法就是, 注入 jackson 的ObjectMapper
@Autowired
private ObjectMapper objectMapper; // 注入
// 輸出JSON字符串
objectMapper.writer().writeValueAsString(javaObj));
// 將JSON字符串轉(zhuǎn)成java bean;
objectMapper.readValue(jsonStr,javaObj.class);
Map<String, Object> map = new HashMap<String, Object>();
// JSON string to Map
map = objectMapper.readValue(json, new TypeReference<Map<String, String>>(){});