问题你提描述
今天再使用Gson处理json数据的时候碰到了一个问题 , 当我使用如下代码解析json数据的时候 , requestTime就变为了double类型
Map<String , Object> sourceValueMap = gson.fromJson(jsonData , new TypeToken<HashMap<String , Object>>(){}.getType());
蓝色框为原始数据 , 红色框为解析之后的数据
解决办法 :
再翻阅了众多资料之后 , 发现有两种解决办法
1.修改源码
2.添加指定类型的自定义解密工具
相对来说第二种解决办法显然更轻松
在上面的代码中,你可以测试网络中找到的其他解决方式,你会发现所有设置都失效了。
原因是,当你使用 Class 对象作为解析类型时,Gson 会转入你自定义的解析器,而使用 TypeToken 时,Gson 无法将传入的参数与绑定的 TypeToken 对应,最终使用默认解析器。
实现过程
创建自定义的 ObjectTypeAdapter 对象,并实现其工厂方法
public final class MapTypeAdapter extends TypeAdapter<Object> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked")
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() == Object.class) {
return (TypeAdapter<T>) new MapTypeAdapter(gson);
}
return null;
}
};
private final Gson gson;
private MapTypeAdapter(Gson gson) {
this.gson = gson;
}
@Override
public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();
//判断字符串的实际类型
switch (token) {
case BEGIN_ARRAY:
List<Object> list = new ArrayList<>();
in.beginArray();
while (in.hasNext()) {
list.add(read(in));
}
in.endArray();
return list;
case BEGIN_OBJECT:
Map<String, Object> map = new LinkedTreeMap<>();
in.beginObject();
while (in.hasNext()) {
map.put(in.nextName(), read(in));
}
in.endObject();
return map;
case STRING:
return in.nextString();
case NUMBER:
String s = in.nextString();
if (s.contains(".")) {
return Double.valueOf(s);
} else {
try {
return Integer.valueOf(s);
} catch (Exception e) {
return Long.valueOf(s);
}
}
case BOOLEAN:
return in.nextBoolean();
case NULL:
in.nextNull();
return null;
default:
throw new IllegalStateException();
}
}
@Override
public void write(JsonWriter out, Object value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
//noinspection unchecked
TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());
if (typeAdapter instanceof ObjectTypeAdapter) {
out.beginObject();
out.endObject();
return;
}
typeAdapter.write(out, value);
}
}
使用自定义工厂方法取代 Gson 实例中的工厂方法。
public class GsonFactory {
public static Gson getGson() {
Gson gson = new GsonBuilder().create();
try {
Field factories = Gson.class.getDeclaredField("factories");
factories.setAccessible(true);
Object o = factories.get(gson);
Class<?>[] declaredClasses = Collections.class.getDeclaredClasses();
for (Class c : declaredClasses) {
if ("java.util.Collections$UnmodifiableList".equals(c.getName())) {
Field listField = c.getDeclaredField("list");
listField.setAccessible(true);
List<TypeAdapterFactory> list = (List<TypeAdapterFactory>) listField.get(o);
int i = list.indexOf(ObjectTypeAdapter.FACTORY);
list.set(i, MapTypeAdapter.FACTORY);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return gson;
}
}
使用
这样的话问题完美解决 , 数据也一切正常