GSON解析常见的问题:com.google.gson.internal.LinkedTreeMap cannot be cast to XXX

Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库。可以将一个 JSON 字符串转成一个 Java 对象,或者反过来。
对象转为字符串

String ps =gson.toJson(person);

字符串转为对象

Person person =gson.fromJson(json, Person.class);

字符串为为list,

List<Person> persons =gson.fromJson(json, new TypeToken<List<Person>>() {}.getType());

这里返回的数据类型是com.google.gson.internal.LinkedTreeMap,如果直接使用会报classCastException:com.google.gson.internal.LinkedTreeMap cannotbecasttocom.yzd.enation.entity.request.AcceptRequest$MaterialTakeInfoListEntity
下面二模块会讲解解决方法;

对象转为字符串,以键值对的方式返回字符串,
字符串转为对象,要注意字符串的格式。格式与对象转换的字符串一样,可以参照。
注意:
需要jar包 gson-2.3.jar,可从gson的官方下载所需版本。
字符串转为对象时,""字符串转出来对象为null,"{}" 转出来有对象,但各个字段为空值。
对象内有list字段时,json字符串的写法

json = "{\"id\":2,\"name\":\"abc\",\"books\":[\"xiqu\",\"wenzhang\",\"xiaoshuo\"]}";

json为list的写法

json = "[{\"id\":2,\"name\":\"abc\",\"books\":[\"xiqu\",\"wenzhang\",\"xiaoshuo\"]},"
+ "{\"id\":3,\"name\":\"def\",\"books\":[\"dianshi\",\"wenzhang\",\"xiaoshuo\"]}]";

代码示例:

import java.util.LinkedList;
import java.util.List;
 
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
 
class Person {
    private long id;
    private String name;
    private List<String> books;
 
    public Person(long id, String name) {
        this.id = id;
        this.name = name;
    }
 
    public Person(long id, String name, List<String> books) {
        this(id, name);
        this.books = books;
    }
 
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public List<String> getBooks() {
        return books;
    }
 
    public void setBooks(List<String> books) {
        this.books = books;
    }
 
    public String toString(){
        return "Person : { id=" + this.id + "  name=" + this.name + "  books=" + this.books + " }";
    }
}
 
public class Gsontest {
    static Gson gson = new Gson();
 
    public static void main(String[] args) {
        toJson();
        fromJson();
    }
 
    static void toJson() {
        List<String> books = new LinkedList<String>();
        books.add("abook");
        books.add("bbook");
        books.add("cbook");
        Person person = new Person(1, "xiao", books);
 
        // 将一个对象转为以键值对表示的字符串,对象内可包含list等都可以
        String ps = gson.toJson(person);
        System.out.println(ps);
 
        // 将一个对象List 转为以键值对表示的字符串
        List<Person> persons = new LinkedList<Person>();
        persons.add(person);
        persons.add(new Person(2, "ming", books));
        System.out.println(gson.toJson(persons));
    }
 
    static void fromJson() {
        // 空字符串转出来对象为null
        String json = "";
        // 提供两个参数,分别是json字符串以及需要转换对象的类型。
        Person person = gson.fromJson(json, Person.class);
        System.out.println(person);
 
        // 注:字符串必须在{}内,list类型包含在[]内,否则转换失败抛异常
        json = "{}";
        // {}内无内容,可以转换成对象,对象不为空,但是各个字段没有值
        person = gson.fromJson(json, Person.class);
        System.out.println(person);
 
        // 注意键值对的写法,如果转换出错,很可能是写法不对,写法可以参照由 toJson 转出来的字符串.
        json = "{\"id\":2,\"name\":\"abc\",\"books\":[\"xiqu\",\"wenzhang\",\"xiaoshuo\"]}";
        person = gson.fromJson(json, Person.class);
        System.out.println(person);
 
        // TypeToken,它是gson提供的数据类型转换器,可以支持各种数据集合类型转换
        json = "[{\"id\":2,\"name\":\"abc\",\"books\":[\"xiqu\",\"wenzhang\",\"xiaoshuo\"]},"
                + "{\"id\":3,\"name\":\"def\",\"books\":[\"dianshi\",\"wenzhang\",\"xiaoshuo\"]}]";
        List<Person> persons = gson.fromJson(json, new TypeToken<List<Person>>() {
        }.getType());
        System.out.println(persons);
    }
}

参考原文链接:https://blog.csdn.net/bingqilin_/article/details/48341093
二,泛型方法 Gson解析 com.google.gson.internal.LinkedTreeMap cannot be cast to XXX
今天遇到问题:明明返回的是自己定义的对象,结果使用时总是报:
classCasteException:
com.google.gson.internal.LinkedTreeMap cannotbecasttocom.yzd.enation.entity.request.AcceptRequest$MaterialTakeInfoListEntity
类转换异常:
百度一下后知道原因了:
先说说我这里的原代码片段:

    public <T> List<T> getDataList(String tag) {
        List<T> datalist=new ArrayList<T>();
        String strJson = preferences.getString(tag, null);
        if (null == strJson) {
            return datalist;
        }
        Gson gson = new Gson();
        datalist = gson.fromJson(strJson, new TypeToken<List<T>>() {
        }.getType());
        return datalist;

    }

修改后的代码片段:

public <T> List<T> getDataList(String message, Class<T> cls){ //这里是Class<T>
        List<T> list = new ArrayList<>();
        String strJson = preferences.getString(message, null);
        if (null == strJson) {
            return list;
        }
        JsonArray jsonArray = new JsonParser().parse(strJson).getAsJsonArray();
        Gson gson = new Gson();
        for (JsonElement jsonElement : jsonArray) {
            list.add(gson.fromJson(jsonElement,cls));
        }
        return list;
    }

从网上参考了一些资料如下,解决的;https://blog.csdn.net/github_38222176/article/details/79198886
今天在尝试用泛型写json解析方法的时候出现了问题,看错误信息就是‘类型’转换问题。调试断点,果然发现这LinkedTreeMap有点不同,如下:
如果代码这样写:

public static <T> List<T> jsonToDto(String message, String jsonHead,T t){//这里是用的T
        JsonObject jsonObject = new JsonParser().parse(message).getAsJsonObject();
        JsonArray jsonArray = jsonObject.getAsJsonArray(jsonHead);

        Gson gson = builder.create();
        List<T> list = new ArrayList<>();
        for (JsonElement jsonElement : jsonArray) {
            t = gson.fromJson(jsonElement,new TypeToken<T>(){}.getType()); // TypeToken
            list.add(t);
        }
        return list;
    }

对应的结果如下:

20180129185847712.png

解释TypeToken

如果这样写:

public static <T> List<T> jsonToDto(String message, String jsonHead,Class<T> cls){ //这里是Class<T>
        JsonObject jsonObject = new JsonParser().parse(message).getAsJsonObject();
        JsonArray jsonArray = jsonObject.getAsJsonArray(jsonHead);

        Gson gson = builder.create();
        List<T> list = new ArrayList<>();
        for (JsonElement jsonElement : jsonArray) {
            list.add(gson.fromJson(jsonElement,cls)); //cls
        }
        return list;
    }

对应的结果如下:


20180129191919619.png

可以看出两种方法解析的结果的结构是不一样的,让我们来看一看下图:


20180130091155086.png

有两个方法对应我上述两段代码,返回类型都是T,当使用第一种方法时返回的是LinkedTreeMap,所以当我把解析后的集合遍历赋值给JavaBean的时候就会报“类型”转换错误的异常。解决方法就是使用第二种方法。或者参考LinkedTreeMap的处理方法

for (TestBean bean : list) {
   ....       
 }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容