欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于Gson的Http请求解析long型日期时出错的解决方案

程序员文章站 2022-07-15 16:08:49
...

在http的post方法中,我们通常使用Gson来实现对象和Json的相互转换。然而,原生的Gson在将包含Date类型对象序列化的过程中,会自动将Date类型转换为long型。此时若想反序列化对象,则Gson将会抛出一个JsonSyntaxException,表示解析失败。

那么为什么会失败呢?通过查看源码可知,Gson默认的日期适配器DateTypeAdapter,只支持这种“yyyy-MM-dd'T'HH:mm:ss'Z'”的字符串日期格式,如图1所示。

基于Gson的Http请求解析long型日期时出错的解决方案

图1

因此,我们可通过重写DateTypeAdapter来达到解析long型日期格式的目的。首先实现Json的反序列化接口,然后重写deserialize方法,同时我们还可通过构造器传入DateFormat对象,以支持特定字符串日期格式的解析,如图2所示。

基于Gson的Http请求解析long型日期时出错的解决方案

图2

最后附上完整的的http工具类(post方法),希望对大家有所帮助。

/**
 * Http工具类
 */
public class HttpUtils {
 
	private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);
	private static final Client CLIENT = Client.create();
	private static final Gson GSON = new GsonBuilder()
	        .registerTypeAdapter(Date.class, new DateTypeAdapter())
	        .create();
 
	private static final String ACCEPT = ":  accept:  ";
	private static final String PATH = "path=  ";
	private static final String APPJSON = "application/json";
	private static final String RESPONSE = ":  response:  ";
 
	/**
	 * 该方法可转换复杂的对象(包含复杂引用类型成员变量)
	 * @param path
	 * @param request
	 * @param describe
	 * @param type
	 * @return
	 */
	public static T post(String path, Object request, String describe, Type type) {
		
		if (request != null) {
			
			logger.info("\n" + describe + ACCEPT + request + "\n" + PATH + path);
			WebResource webResource = CLIENT.resource(path);
 
			String response = webResource.accept(APPJSON).type(APPJSON).post(String.class, new Gson().toJson(request));
			logger.info("\n" + describe + RESPONSE + response);
			
			return GSON.fromJson(response, type);
		}
 
		return null;
	}
	
	/**
	 * 该方法可转换复杂的对象(包含复杂引用类型成员变量),同时还可添加请求头信息
	 * @param path
	 * @param header
	 * @param request
	 * @param describe
	 * @param type
	 * @return
	 */
	public static T postWithHeader(String path, Map<String, String> header, Object request,
			String describe, Type type) {
		
		if (request != null) {
			
			logger.info("\n" + describe + ACCEPT + request + "\n" + PATH + path);
			WebResource webResource = CLIENT.resource(path);
			Builder builder = webResource.getRequestBuilder();
			for (Map.Entry<String, String> entry : header.entrySet()) {
				builder = builder.header(entry.getKey(), entry.getValue());
			}
			String response = builder.accept(APPJSON).type(APPJSON).post(String.class, new Gson().toJson(request));
			logger.info("\n" + describe + RESPONSE + response);
			
			return GSON.fromJson(response, type);
		}
 
		return null;
	}
}
 
/**
* 重写日期类型适配器
* 默认日期类型为Long型,若日期格式为String类型,则必须通过构造器传入对应DateFormat类型进行日期转换
*/
class DateTypeAdapter implements JsonDeserializer<Date> {
 
    private DateFormat format;
 
    public DateTypeAdapter() {
 
    }
 
    public DateTypeAdapter(DateFormat format) {
 
        this.format = format;
    }
 
    public synchronized Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
 
        if (!(json instanceof JsonPrimitive)) {
            throw new JsonParseException("This is not a primitive value");
        }
 
        String jsonStr = json.getAsString();
 
        if (format != null) {
 
            try {
                return format.parse(jsonStr);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
 
        return new Date(Long.parseLong(jsonStr));
    }
}