前言:平常开发中,与json打交道的机会不少,通常对象json转都不会出现什么问题,可是json转对象就有可能出现问题了,今天就来讲说json转map致使int型转换成double的问题json
public class MyType<T> {
public T gsonToMap(String strJson) {
return new Gson().fromJson(strJson, new TypeToken<T>() {
}.getType());
}
}
String json = "{\"identifier\":\"18111111111\",\"opType\":1,\"platform\":0}";
Map<String, Object> map = new MyType<Map<String, Object>>().gsonToMap(json);
复制代码
接下来的操做你们都知道了,借助于网络平台,因而乎找到几种解决方式,细心的我发现有人评论解决他们的问题,看来有戏啊【手动滑稽】bash
一、须要gson解析的类型 , 重写他的deserialize方法, 就是将其中json手动解析成map , 不对数据进行处理网络
public HashMap<String,Object> gsonToMap(String strJson) {
Gson gson = new GsonBuilder()
.registerTypeAdapter(
new TypeToken<HashMap<String,Object>>(){}.getType(),
new JsonDeserializer<HashMap<String, Object>>() {
@Override
public HashMap<String, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
HashMap<String, Object> hashMap = new HashMap<>();
JsonObject jsonObject = json.getAsJsonObject();
Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
for (Map.Entry<String, JsonElement> entry : entrySet) {
hashMap.put(entry.getKey(), entry.getValue());
}
return hashMap;
}
}).create();
return gson.fromJson(strJson, new TypeToken<HashMap<String,Object>>() {
}.getType());
}
复制代码
二、自定义TypeAdapter替代Gson默认的adapter(此处埋下伏笔【偷笑】)解决,自定义TypeAdapter以下:ide
public class MapTypeAdapter extends TypeAdapter<Object> {
private final TypeAdapter<Object> delegate = new Gson().getAdapter(Object.class);
@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:
/**
* 改写数字的处理逻辑,将数字值分为整型与浮点型。
*/
double dbNum = in.nextDouble();
// 数字超过long的最大值,返回浮点类型
if (dbNum > Long.MAX_VALUE) {
return String.valueOf(dbNum);
}
// 判断数字是否为整数值
long lngNum = (long) dbNum;
if (dbNum == lngNum) {
return String.valueOf(lngNum);
} else {
return String.valueOf(dbNum);
}
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 {
delegate.write(out,value);
}
}
复制代码
public T gsonToMap(String strJson) {
Gson gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<T>(){}.getType(),new MapTypeAdapter()).create();
return gson.fromJson(strJson, new TypeToken<T>() {
}.getType());
}
String json = "{\"identifier\":\"18111111111\",\"opType\":1,\"platform\":0}";
Map<String, Object> map = new MyType<Map<String, Object>>().gsonToMap(json);
复制代码
public static Map<String, Object> gsonToMap(String strJson) {
Gson gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<Map<String,Object>>(){}.getType(),new MapTypeAdapter()).create();
return gson.fromJson(strJson, new TypeToken<Map<String, Object>>() {
}.getType());
}
String json = "{\"identifier\":\"18111111111\",\"opType\":1,\"platform\":0}";
Map<String, Object> map = new MyType<Map<String, Object>>().gsonToMap(json);
复制代码
上述方案的确是能够解决个人问题,可是却给我留下了疑问;本着知其然知其因此然的目的,以为解决这些疑惑工具
一、关于泛型这里就要提到 泛型擦除,及泛型只在编译阶段有效,运行时就无效了ui
public abstract class TypeAdapter<T>
复制代码
二、int转double,其实这是Gson在源码中故意为之的,其实不只是int,long也会转化成double,接下来咱们去寻找证据this
处理double:
private TypeAdapter<Number> doubleAdapter(boolean serializeSpecialFloatingPointValues) {
if (serializeSpecialFloatingPointValues) {
return TypeAdapters.DOUBLE;
}
return new TypeAdapter<Number>() {
@Override public Double read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return in.nextDouble();
}
@Override public void write(JsonWriter out, Number value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
double doubleValue = value.doubleValue();
checkValidFloatingPoint(doubleValue);
out.value(value);
}
};
}
处理float:
private TypeAdapter<Number> floatAdapter(boolean serializeSpecialFloatingPointValues) {
if (serializeSpecialFloatingPointValues) {
return TypeAdapters.FLOAT;
}
return new TypeAdapter<Number>() {
@Override public Float read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return (float) in.nextDouble();
}
@Override public void write(JsonWriter out, Number value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
float floatValue = value.floatValue();
checkValidFloatingPoint(floatValue);
out.value(value);
}
};
}
复制代码
public final class ObjectTypeAdapter 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 ObjectTypeAdapter(gson);
}
return null;
}
};
private final Gson gson;
ObjectTypeAdapter(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<Object>();
in.beginArray();
while (in.hasNext()) {
list.add(read(in));
}
in.endArray();
return list;
case BEGIN_OBJECT:
Map<String, Object> map = new LinkedTreeMap<String, Object>();
in.beginObject();
while (in.hasNext()) {
map.put(in.nextName(), read(in));
}
in.endObject();
return map;
case STRING:
return in.nextString();
case NUMBER:
return in.nextDouble();
case BOOLEAN:
return in.nextBoolean();
case NULL:
in.nextNull();
return null;
default:
throw new IllegalStateException();
}
}
@SuppressWarnings("unchecked")
@Override public void write(JsonWriter out, Object value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());
if (typeAdapter instanceof ObjectTypeAdapter) {
out.beginObject();
out.endObject();
return;
}
typeAdapter.write(out, value);
}
}
复制代码
case NUMBER:
return in.nextDouble();
复制代码