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