描述
通过google的gson 将json String串转成 Map时,里面如果有Long或Int类型会被转成浮点型。
原始数据
{"Param":{"stringtype":"This is String","timestamp":1597817205000,"arr":[12334,2323,334344],"double":7.0},"Type":"/api/test/getName"}
代码
String json = "{\"Param\":{\"stringtype\":\"This is String\",\"timestamp\":1597817205000,\"arr\":[12334,2323,334344],\"double\":7.0},\"Type\":\"/api/test/getName\"}";
Gson gson = new Gson();
Map<String, Object> objectMap = gson.fromJson(json, new TypeToken<Map<String, Object>>() {
}.getType());
System.out.println(objectMap);
运行结果
{Param={stringtype=This is String, timestamp=1.597817205E12, arr=[12334.0, 2323.0, 334344.0], double=7.0}, Type=/api/test/getName}
我们可以看到timestamp=1.597817205E12, arr=[12334.0, 2323.0, 334344.0]
数据格式变了。
为什么会出现整型数据被转成浮点型数据?
我们结合网上的提示及原码,定位到了ObjectTypeAdapter。
ObjectTypeAdapter#read(JsonReader in)
...
//这里,所有的NUMBER都当成Double来处理
case NUMBER:
return in.nextDouble();
....
解决方案
方案一 重写ObjectTypeAdapter
CustomizedObjectTypeAdapter#read(JsonReader in)
...
case NUMBER:
//return in.nextDouble();
String n = in.nextString();
if (n.indexOf('.') != -1) {
return Double.parseDouble(n);
}
return Long.parseLong(n);
....`
自定义的CustomizedObjectTypeAdapter类
class CustomizedObjectTypeAdapter extends TypeAdapter<Object> {
private final TypeAdapter<Object> delegate = new Gson().getAdapter(Object.class);
@Override
public void write(JsonWriter out, Object value) throws IOException {
delegate.write(out, value);
}
@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();
String n = in.nextString();
if (n.indexOf('.') != -1) {
return Double.parseDouble(n);
}
return Long.parseLong(n);
case BOOLEAN:
return in.nextBoolean();
case NULL:
in.nextNull();
return null;
default:
throw new IllegalStateException();
}
}
}
调用
String json = "{\"Param\":{\"stringtype\":\"This is String\",\"timestamp\":1597817205000,\"arr\":[12334,2323,334344],\"double\":7.0},\"Type\":\"/api/test/getName\"}";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(new TypeToken<Map<String, Object>>() {
}.getType(), new CustomizedObjectTypeAdapter());
Gson gson = gsonBuilder.create();
Map<String, Object> objectMap = gson.fromJson(json, new TypeToken<Map<String, Object>>() {
}.getType());
System.out.println(objectMap);
运行结果
{Param={stringtype=This is String, timestamp=1597817205000, arr=[12334, 2323, 334344], double=7.0}, Type=/api/test/getName}
可以看到整型数据保持不变。
方案二 使用Jackson
如果你使用jackson框架来解析json,上面的问题就不存在。
相关调用
String json = "{\"Param\":{\"stringtype\":\"This is String\",\"timestamp\":1597817205000,\"arr\":[12334,2323,334344],\"double\":7.0},\"Type\":\"/api/test/getName\"}";
TypeReference<Map<String, Object>> typeRef
= new TypeReference<Map<String, Object>>() {};
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> objectMap = null;
try {
objectMap = mapper.readValue(json, typeRef);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
System.out.println(objectMap);
运行结果
{Param={stringtype=This is String, timestamp=1597817205000, arr=[12334, 2323, 334344], double=7.0}, Type=/api/test/getName}