问题描述
Gson泛型解析时Json报错:com.google.gson.internal.LinkedTreeMap cannot be cast to xxx
先看下返回的Json数据格式
{
"code": 200,
"data": [
{
"id": null,
"type": "free",
"name": "免费数字教材",
"totals": null,
"books": [
{
"ebook_type": "0",
"author": "测试作者",
"isfree": "0",
"isbn": "9787040144390",
"title": "测试标题1",
"type": 0,
"url": "http://d7.ixdzs.com/66/66746/66746.epub",
"download_count": 234,
"cover": "https://pic4.zhimg.com/017d7c47843b8816a0ab583d37628947_xld.jpg",
"addtime": 1493869462000,
"id": 4,
"press": "测试出版社",
"introduction": "简介",
"likes": 1
}
...
]
}
],
"msg": "ok",
"app_key": null
}
然后是通用的接口处理类
public class RootBean<T> extends BaseEntity.BaseBean {
/**
* code : 200
* data : []
* msg : ok
* app_key : null
*/
private int code;
private String msg;
private Object app_key;
private T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getApp_key() {
return app_key;
}
public void setApp_key(Object app_key) {
this.app_key = app_key;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return "RootBean{" +
"code=" + code +
", msg='" + msg + '\'' +
", app_key=" + app_key +
", data=" + data +
'}';
}
}
错误原因
原因是没有为泛型指定明确的类型,导致Java类型擦除异常。
解决
在该接口所有使用RootBean< T >的方法或参数中指定T的类型,即RootBean< List < DataBean > >,List < DataBean >为最终要取出的数据。
贴一下相关的代码:
Api请求层
/**
* 首页推荐 List
* http://192.168.100.158/portal/app/find/recommends
*
* @return
*/
@GET("find/recommends")
Observable<RootBean<List<DataBean>>> findRecommends();
Contract 层
public interface FindContract {
interface Model extends BaseModel {
/**
* 获取发现页面的数据
*
* @return
*/
Observable<RootBean<List<DataBean>>> findRecommends();
}
interface View extends BaseView {
/**
* 用于页面显示数据
*
* @param rootBean
*/
void findRecommends(RootBean<List<DataBean>> rootBean);
/**
* 显示错误提示
*
* @param e
*/
void displayError(Throwable e);
}
abstract class Presenter extends BasePresenter<Model, View> {
abstract void findRecommends();
@Override
public void onAttached() {
}
}
}
Model层
public class FindModel implements FindContract.Model {
@Override
public Observable<RootBean<List<DataBean>>> findRecommends() {
return ApiManager.getInstance().mApiService.findRecommends()
.compose(RxSchedulers.<RootBean<List<DataBean>>>applySchedilers());
}
}
Presenter层
public class FindPresenter extends FindContract.Presenter {
@Override
public void findRecommends() {
mModel.findRecommends().subscribe(new Observer<RootBean<List<DataBean>>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
mView.displayError(e);
}
@Override
public void onNext(RootBean<List<DataBean>> rootBean) {
mView.findRecommends(rootBean);
}
});
}
}
UI层
public class FindFragment extends BaseFragment<FindPresenter, FindModel> implements FindContract.View {
/*首页数据的集合*/
List<DataBean> mDataBeanList;
List<BannersBean> mBannersBeanList;
List<BooksBean> mBooksBeanList;//纸质教材集合
/*复杂布局的适配器*/
private MultiTypeAdapter mAdapter;
private Items mItems;//Items 等同于 ArrayList<Object>
/*控件*/
@BindView(R.id.rv_content)
RecyclerView content_rv;//根RecyclerView
@BindView(R.id.swipeRefresh)
SwipeRefreshLayout swipeRefreshLayout;//刷新控件
public FindFragment() {
}
public static FindFragment newInstance() {
FindFragment fragment = new FindFragment();
return fragment;
}
@Override
protected int getLayoutId() {
return R.layout.fragment_find;
}
@Override
protected void initView() {
/*刷新下拉刷新样式*/
swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary,
R.color.red);//设置刷新控件的颜色
//注册类型和View的对应关系
mAdapter = new MultiTypeAdapter();
//轮播图
mAdapter.register(BannersListBean.class, new BannersViewBinder(mContext));
//列表标题头
mAdapter.register(HeaderBean.class, new HeaderViewBinder());
//教材推荐
mAdapter.register(BooksListBean.class, new BooksViewBinder(mContext));
/*设置RV布局方式*/
LinearLayoutManager layoutManager = new LinearLayoutManager(mContext);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
content_rv.setLayoutManager(layoutManager);
content_rv.setAdapter(mAdapter);
}
@Override
protected void initData() {
swipeRefreshLayout.setRefreshing(true);//加载界面时刷新
mPresenter = new FindPresenter();
mPresenter.setMV(new FindModel(), this);
mPresenter.findRecommends();//获取推荐信息
}
@Override
public void findRecommends(RootBean<List<DataBean>> rootBean) {
// 加载完数据设置为不刷新状态,将下拉进度收起来
swipeRefreshLayout.setRefreshing(false);
if (rootBean != null) {
mBannersBeanList = new ArrayList<>();
//添加轮播图数据
mBannersBeanList.add(new BannersBean("https://pic4.zhimg.com/v2-0a5e49bf27ffc7fbc13350e29408e9bf.jpg",
"https://www.zhihu.com/publications/book/119554452"));
//mDataBeanList = JsonUtil.stringToArray(rootBean.getData().toString(), DataBean[].class);
mDataBeanList = rootBean.getData();
//模拟加载数据
mItems = new Items();
for (DataBean d : mDataBeanList) {
//保证只填充一次
if ("free".equals(d.getType())) {
mItems.add(new BannersListBean(mBannersBeanList));
}
mItems.add(new HeaderBean(d.getName()));
mBooksBeanList = d.getBooks();
mItems.add(new BooksListBean(mBooksBeanList));
}
mAdapter.setItems(mItems);
mAdapter.notifyDataSetChanged();
}
}
@Override
public void displayError(Throwable e) {
// 加载完数据设置为不刷新状态,将下拉进度收起来
swipeRefreshLayout.setRefreshing(false);
Timber.tag(TAG).e(e.toString());
}
@Override
protected void initEvent() {
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mPresenter.findRecommends();
}
});
}
参考
http://blog.youkuaiyun.com/anddroid_lanyan/article/details/46561341
当尝试将Json数据转换为特定类型时,遇到'com.google.gson.internal.LinkedTreeMap cannot be cast to xxx'的错误。原因是Java泛型类型擦除,未指定明确的类型导致。解决方案是在接口处理类中为泛型指定确切的类型,如RootBean<List<DataBean>>,确保数据能正确解析。涉及的代码包括Api请求层、Contract层、Model层、Presenter层和UI层。

被折叠的 条评论
为什么被折叠?



