呼叫RESTFul服務,用Gson序列化返回物件
阿新 • • 發佈:2019-01-07
一個應用使用 Spring Mvc 實現的 RESTFul Webservice,其Controller 用下面的類包裝結果返回給呼叫方。
public class BaseResponse<T> { private String msg = "message not set"; private T data; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
我們呼叫方就直接使用 Spring 的 RestTemplate 呼叫其服務,呼叫過程中發現如果有個時間欄位被序列化成 Long 型,會導致簡單的 Gson 反序列化出問題。網上搜了下解決方案蠻多,就抄了個下面的:
public class GsonUtil { public static Gson getDateGson() { JsonDeserializer<Date> dateJsonDeserializer = (json, typeOfT, context) -> json == null ? null : new Date(json.getAsLong()); return new GsonBuilder().registerTypeAdapter(Date.class,dateJsonDeserializer).create(); } }
然後封裝下 RestTemplate:
public class SpringRest<T> { private Type type; private RestTemplate rest; public SpringRest(Type type){ rest = new RestTemplate(); this.type = type; } public T doGet(String url){ ResponseEntity<String> entity = rest.getForEntity(url, String.class); return getResult(entity); } public T doPost(String url, Object input){ ResponseEntity<String> entity = rest.postForEntity(url, input, String.class); return getResult(entity); } private T getResult(ResponseEntity<String> entity) { String str = entity.getBody(); BaseResponse<T> resp = GsonUtil.getDateGson().fromJson(str, type); return resp.getData(); } }
這裡本來不打算定義 type 屬性,而是直接在 getResult 方法的 fromJson 裡直接傳如 new TypeToken<BaseResponse<T>>() {}.getType(),也即:
BaseResponse<T> resp = GsonUtil.getDateGson().fromJson(str, new TypeToken<BaseResponse<T>() {}.getType());
但真正執行時,不起作用,T 不能執行時替換成實際型別,所以把 type 的例項作為建構函式的引數傳入。測試程式碼:
public class Test {
public static void main(final String[] args) throws Exception {
SpringRest<List<Project>> rest = new SpringRest<>(new TypeToken<BaseResponse<List<Project>>>() {}.getType());
List<Project> projects = rest.doGet("http://localhost:8090/MyApp/project/21/projects");
for (Project p : projects){
System.out.println(p.getName());
}
}
}