我正在编写一个将连接到服务器的类,并基于一些参数,检索一个json字符串,该字符串将与GSON一起html" target="_blank">解析为指定的(通过泛型)类。
负责班级的精简版看起来像这样:
class Executor<T> {
private Response<T> response;
public void execute() {
Type responseType = new TypeToken<Response<T>>() {}.getType();
this.response = new Gson().fromJson(json, responseType);
}
public Response<T> getResponse() { return this.response; }
}
(JSON
-variable 看起来像这样。)
反序列化后存储数据的类如下所示:
class Response<T> {
private List<T> data = null;
public List<T> getData() { return this.data; }
}
数据正试图反序列化的类:
public class Language {
public String alias;
public String label;
}
运行的代码利用了上面的类:
Executor<Language> executor = new Executor<Language();
List<Language> languages = executor.execute().getResponse().getData();
System.out.println(languages.get(0).alias); // exception occurs here
导致以下异常
ClassCastException:com.google.gson.internal.StringMap无法转换为sunnerberg.skolbibliotek.book.Language
任何帮助或建议,我们将不胜感激!
简短的答案是,您需要移动TypeToken
out 的创建,在创建标记()时Executor
将T
in
绑定,然后将类型标记传递给构造函数。Response<T>``new TypeToken<Response<Language>>() {}``Executor
长答案是:
类型上的泛型通常在运行时删除,除非使用泛型参数绑定 编译 类型。在这种情况下,编译器会将泛型类型信息插入已编译的类中。在其他情况下,这是不可能的。
因此,例如,请考虑:
List<Integer> foo = new ArrayList<Integer>();
class IntegerList extends ArrayList<Integer> { ... }
List<Integer> bar = new IntegerList();
在运行时,Java 知道
bar
包含整数,因为Integer
类型是ArrayList
在编译时绑定的,因此泛型类型信息保存在IntegerList
类文件中。但是,的通用类型信息foo
已删除,因此在运行时实际上不可能确定foo
应该包含Integer
。
因此经常会出现这样的情况,即在正常情况下会在运行时将其擦除的情况下,例如在GSON中解析JSON数据的情况下,我们需要通用类型信息。在这些情况下,我们可以利用这样的事实,即类型信息在编译时IntegerList
通过使用类型标记(在上面的示例中)进行绑定而得以保留,而这些标记实际上只是可以方便地存储泛型类型信息的微小匿名类。
现在到您的代码:
Type responseType = new TypeToken<Response<T>>() {}.getType();
在您的Executor
类的这一行中,我们创建一个匿名类(从继承TypeToken
),其类型Response<T>
在编译时进行了硬编码(绑定)。因此,在运行时,GSON能够确定您需要的对象Response<T>
。但是它不知道是什么T
,因为您没有在编译时指定它!因此,GSON无法确定它创建List
的Response
对象的类型是什么,而只是创建了一个StringMap
。
这个故事的寓意是您需要T
在编译时指定它。如果Executor
要一般使用,则可能需要在客户端代码中在该类之外创建类型标记。就像是:
class Executor<T> {
private TypeToken<Response<T>> responseType;
private Response<T> response;
public Executor(TypeToken<Response<T>> responseType) {
this.responseType = responseType;
}
public void execute() {
this.response = new Gson().fromJson(json, responseType.getType());
}
public Response<T> getResponse() { return this.response; }
}
// client code:
Executor<Language> executor = new Executor<Language>(new TypeToken<Response<Language>>() { });
executor.execute();
List<Language> languages = executor.getResponse().getData();
System.out.println(languages.get(0).alias); // prints "be"
顺便说一句,我确实在我的机器上测试了以上内容。
抱歉,时间太长!
问题内容: 我有一个名为的类,该类具有一个作为参数的构造函数: 具有以下属性: 并且是我的应用程序的其他类,并具有以下构造函数: ,并且是的子类。 我想用Gson 反序列化数组,所以我写道: 以定义为: 调试时,实例具有正确的“ MainActivity”作为上下文,而其成员变量的上下文为null。 Gson 使用正确的构造函数创建了对象,但使用默认的无参数构造函数创建了实例。我怎样才能解决这个问
我有一个名为PageItem的类,它有一个构造函数,该构造函数将上下文作为参数: 具有以下属性: 新闻提供者(Newsprovider)和主题(Topic)是我的应用程序的其他类,具有以下构造函数:
问题内容: 所有,我都有以下输出/字符串(它是JIRA API的响应): 我用于遍历元素并获取值。我在下面的“嵌套对象”示例中编写了类 http://www.javacreed.com/gson-deserialiser- example/ 我能够获得到第二级的元素值。例如:在此级别之前,我能够获得的值以及其他值。我如何获得的价值? 我应该如何构造我的解串器和类。请协助。谢谢。 问题答案: 试试这
问题内容: 我在Android应用程序(带有Gson库)中实现Json反序列化存在一些问题 我已经上了这样的课 反序列化的调用是: 问题是调用后的result.posts列表包含一个LinkedTreeMap对象数组(具有正确的值,因此问题是反序列化)而不是MyJson对象。当我使用MyObject而不是T时,一切运行正常并且MyObject是正确的。 那么,有什么方法可以在不创建自定义反序列化器
问题内容: 根据该 GSON可以反序列化内部类。我有JSON字符串的下一个片段: 我正在使用下一堂课: 并尝试解析我的JSON字符串: 但是我得到这个错误: 您能告诉我错误在哪里吗? 问题答案: 当我将Gson与嵌套类一起使用时,我总是需要使它们起作用。在您的链接中,他们说这是没有必要的,但是在 Gson文档中 明确指出: “ Gson还可以反序列化静态嵌套类。但是,Gson不能自动反序列化纯内部
问题内容: 在我当前的项目中,我在android中使用GSON库,并且遇到了嵌套地图反序列化的问题。这就是初始json的样子 而我的pojo的 和花类 但是当我尝试反序列化此对象时,我可以访问嵌套的哈希图,示例代码为 有什么建议? 问题答案: 这告诉Gson您想反序列化为未知值类型的Map。您可能会想指定类似的东西,但是您无法在Java中进行指定,因此解决方案是使用他们在Gson中称为TypeTo