java - 有没有办法让改造/gson 将双时间戳转换为长?
问题描述
我正在开发一个Android
应用程序。我正在使用改造Gson
来调用服务器并序列化/反序列化。在请求中,有一个包含timestamp
( long
) 的响应类。有时这是double
因为iOS
应用程序的版本double
用于存储时间戳。
有没有办法强制Gson
反序列化响应并转换为Response
类(长)上存在的对象?
例外:
Caused by com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: Expected a long but was 1555323142345.364 at line 1 column 1002 path $.userSettings.stories[4].readTimestamp
at com.google.gson.internal.bind.TypeAdapters$11.read(TypeAdapters.java:323)
at com.google.gson.internal.bind.TypeAdapters$11.read(TypeAdapters.java:313)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:119)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:218)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:180)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:91)
at inesc_id.pt.motivandroid.motviAPIClient.MotivAPIClientManager$CheckOnboardingNeededAndRetrieve.doInBackground(MotivAPIClientManager.java:909)
at inesc_id.pt.motivandroid.motviAPIClient.MotivAPIClientManager$CheckOnboardingNeededAndRetrieve.doInBackground(MotivAPIClientManager.java:711)
at android.os.AsyncTask$2.call(AsyncTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:833)
班级:
public class StoryStateful implements Serializable{
@Expose
int storyID;
@Expose
boolean read;
@Expose
long readTimestamp;
@Expose
long availableTimestamp;
}
解决方案
为简单起见,假设您的JSON
有效负载是:
{
"timestamp": 1555323142345.345
}
它应该适合:
class Pojo {
private long timestamp;
// getters, setters, toString
}
解决方案取决于您是否可以更改Pojo
模型。如果是并且您想要存储double
并且long
可以将类型更改为Number
:
private Number timestamp;
你应该能够解析double
' 和long
' 的时间戳。如果您总是想要long
实现自定义反序列化器:
class LongOrDoubleJsonDeserializer implements JsonDeserializer<Long> {
@Override
public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonPrimitive()) {
Number number = json.getAsNumber();
return number.longValue();
}
return null;
}
}
您的Pojo
财产应如下所示:
@JsonAdapter(LongOrDoubleJsonDeserializer.class)
private long timestamp;
如果您无法更改Pojo
课程,则需要TypeAdapterFactory
使用自定义和注册GsonBuilder
。请参阅此链接:创建改造实例。自定义实现可能如下所示:
class LongOrDoubleTypeAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Class<? super T> rawType = type.getRawType();
if (rawType == Long.class || rawType == long.class) {
return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) {
}
@Override
public T read(JsonReader in) throws IOException {
try {
return (T) new Long(in.nextLong());
} catch (NumberFormatException e) {
return (T) new Long(((Double) in.nextDouble()).longValue());
}
}
};
}
return null;
}
}
并注册如下:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new LongOrDoubleTypeAdapterFactory())
.create();
推荐阅读
- python - 为什么 pandas 会自动将我的 csv 中的所有表连接到两列?
- biztalk - 在编排接收形状中按 BTS.ReceiveLocationName 过滤
- mysql - SSL 证书上的 Google 云 (GCP) SQL 限制
- php - Symfony 序列化程序忽略序列化组
- r - 是否有一种简单的方法可以在 R 的 igraph 中按度数对网络节点进行着色?
- angularjs - 为什么 AngularJS $resources 不能在我的机器上解析?
- sql - 在 SQL Server 2019 中编写对目标对象进行更改查询的脚本
- linux - linux如何检测网络的协议?
- vuejs2 - Nuxt 通用应用程序。服务器端的 Vuex 存储在请求之间缓存,而与用户的机器无关
- java - 部署时服务器错误为 java.lang.reflect.MalformedParameterizedTypeException