概述
情况说明
需要解析的json
{
"status": 200,
"msg": "OK",
"data": [
{
"id": 1,
"username": "eric",
"password": "123456",
"age": 29,
"sex": 0,
"permission": 0,
"isDel": 0
}
]
}
类的定义
@Data
public class ResponseData implements Serializable {
// 响应业务状态
private Integer status;
// 响应消息
private String msg;
// 响应中的数据
private Object data;
}
解析后
ResponseData(status=200, msg=OK, data=[{id=1.0, username=eric, password=123456, age=29.0, sex=0.0, permission=0.0, isDel=0.0}])
进行处理后,变为
{
"status": 200,
"msg": "OK",
"data": [
{
"id": 1.0,
"username": "eric",
"password": "123456",
"age": 29.0,
"sex": 0.0,
"permission": 0.0,
"isDel": 0.0
}
]
}
问题分析
Object最后默认的TypeAdapter使用的是com.google.gson.internal.bind包下的ObjectTypeAdapter,处理如下
/**
* Adapts types whose static type is only 'Object'. Uses getClass() on
* serialization and a primitive/Map/List on deserialization.
*/
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);
}
}
查看read方法发现所有的Number类型都被转成了double类型
,想要修改掉这个问题,需要自己实现一个TypeAdapter,处理Number类型的问题,自己重写TypeAdapter
解决
上面我们分析后,是需要去重写TypeAdapter方法,在重写的这个方法里面,我们需要将其写出为对应的方法
第一步:重写TypeAdapter方法
public class ResponseDataTypeAdaptor extends TypeAdapter<ResponseData> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked")
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() == ResponseData.class) {
return (TypeAdapter<T>) new ResponseDataTypeAdaptor(gson);
}
return null;
}
};
private final Gson gson;
ResponseDataTypeAdaptor(Gson gson) {
this.gson = gson;
}
@Override
public void write(JsonWriter out, ResponseData value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.beginObject();
out.name("status");
gson.getAdapter(Integer.class).write(out, value.getStatus());
out.name("msg");
gson.getAdapter(String.class).write(out, value.getMsg());
out.name("data");
gson.getAdapter(Object.class).write(out, value.getData());
out.endObject();
}
@Override
public ResponseData read(JsonReader in) throws IOException {
ResponseData data = new ResponseData();
Map<String, Object> dataMap = (Map<String, Object>) readInternal(in);
data.setStatus((Integer) dataMap.get("status"));
data.setMsg((String) dataMap.get("msg"));
data.setData(dataMap.get("data"));
return data;
}
private Object readInternal(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(readInternal(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(), readInternal(in));
}
in.endObject();
return map;
case STRING:
return in.nextString();
case NUMBER:
String numberStr = in.nextString();
if (numberStr.contains(".") || numberStr.contains("e") || numberStr.contains("E")) {
return Double.parseDouble(numberStr);
}
if (Long.parseLong(numberStr) <= Integer.MAX_VALUE) {
return Integer.parseInt(numberStr);
}
return Long.parseLong(numberStr);
case BOOLEAN:
return in.nextBoolean();
case NULL:
in.nextNull();
return null;
default:
throw new IllegalStateException();
}
}
}
第二步:注册gson
将自己重写的TypeAdapter注册一下
private static Gson buildGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapterFactory(DataTypeAdaptor.FACTORY);
return gsonBuilder.create();
}
第三步:测试
public class GsonTest {
public static void main(String[] args) {
String dataJson = "{"status":200,"msg":"OK","data":[{"id":1,"username":"eric","password":"123456","age":29,"sex":0,"permission":0,"isDel":0}]}";
Gson gson = buildGson();
ResponseData data = gson.fromJson(dataJson, ResponseData.class);
System.out.println(data.toString());
}
}
其他问题
解析过程中,还会出现转换问题,如:
com.google.gson.internal.LinkedTreeMap cannot be cast to XXX
问题1:LinkedTreeMap cannot be cast to XXX
这种情况出现的原因是:
进行到对list进行操作的那步,报错了(java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to xx)。原来list中的数据是LinkedTreeMap 格式的,并没有转换成对应的实体类。
那么现在就需要自己去改写一下之前所重写的TypeAdapter方法
问题1:解决
去遍历这个LinkedTreeMap 这个Map
LinkedTreeMap,可通过key来获取value的map
如下去一步一步遍历,将遍历的结果设置到对应的实体类中
LinkedTreeMap tm = (LinkedTreeMap)fromJson2;
Iterator it = tm.keySet().iterator();
while (it.hasNext()) {
String key = (String) it.next();
String value = (String)tm.get(key);
}
最后
以上就是暴躁紫菜为你收集整理的Gson转换错误导致Int变为Double类型情况说明解决其他问题的全部内容,希望文章能够帮你解决Gson转换错误导致Int变为Double类型情况说明解决其他问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复