1. 程式人生 > >呼叫RESTFul服務,用Gson序列化返回物件

呼叫RESTFul服務,用Gson序列化返回物件

一個應用使用 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());
		}
    } 
}