Gson ClassCastException(LinkedTreeMap)
Gson ClassCastException (LinkedTreeMap)
使用 Gson
反序列化参数化 class Container<T>
的对象,导致 T
的某些值的 java.lang.ClassCastException
,例如对于由 String
和 List<String>
字段组成的简单 Record
类型:
com.google.gson.internal.LinkedTreeMap cannot be cast to Record
有趣的是,相同的代码在内联调用 fromJson()
方法时有效,即以下语句 return 一个有效值:
Container<Record> value = new Gson().fromJson(
json, new TypeToken<Container<Record>>(){}.getType());
Container<T>
的定义也很简单:
public class Container<T> {
private static final Gson PARSER = new Gson();
private String id;
private List<T> content;
private Object data;
public static <T> Container<T> deserialize(String json, Class<T> type) {
return PARSER.fromJson(json, new TypeToken<Container<T>>(){}.getType());
}
}
将 deserialize()
方法更改为非静态方法无法解决问题。
有什么想法吗?
你想要 ParameterizedType 我的解决方案是创建
public static <T> Container<T> deserialize(String json, Class<T> clazz) {
Type type = TypeToken.getParameterized(Container.class,clazz).getType();
return new Gson().fromJson(json, type);
}
问题是 T,因为 Java 不知道我的类型并生成 T 的类型
public static <T> Container<T> sec(String json, Class<T> clazz) {
Type type1 = new TypeToken<Container<T>>() { }.getType();
Type type = TypeToken.getParameterized(Container.class,clazz).getType();
System.out.println(type1); //==>pl.jac.container.Container<T>
System.out.println(type); //==>pl.jac.container.Container<pl.jac.container.Record>
return new Gson().fromJson(json, type);
}
这是测试更多示例以更正 运行
测试 testContainerRecord2 是针对你的问题
import java.lang.reflect.Type;
import org.junit.Test;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import static org.junit.Assert.assertEquals;
public class ContainerTest {
@Test
public void testContainerRecord() {
//given
String json = "{\"id\":\"new ID\",\"content\":[{\"id\":\"50e0300a-6668-42b3-a474-81a6a08f773f\"},{\"id\":\"f0bee3f3-2c40-4b44-8608-a6fedb226b7a\"}],\"data\":\"AAAAAAAA\"}";
//when
Container<Record> containerRecord = Container.deserializeClass(json, ContainerRecord.class);
//then
assertEquals("50e0300a-6668-42b3-a474-81a6a08f773f", containerRecord.content.get(0).id);
assertEquals("f0bee3f3-2c40-4b44-8608-a6fedb226b7a", containerRecord.content.get(1).id);
}
@Test
public void testContainerRecord2() {
//given
String json = "{\"id\":\"new ID\",\"content\":[{\"id\":\"50e0300a-6668-42b3-a474-81a6a08f773f\"},{\"id\":\"f0bee3f3-2c40-4b44-8608-a6fedb226b7a\"}],\"data\":\"AAAAAAAA\"}";
//when
Container<Record> containerRecord = Container.deserialize(json, Record.class);
//then
assertEquals("50e0300a-6668-42b3-a474-81a6a08f773f", containerRecord.content.get(0).id);
assertEquals("f0bee3f3-2c40-4b44-8608-a6fedb226b7a", containerRecord.content.get(1).id);
}
@Test
public void testGenericWithType() {
//given
String json = "{\"id\":\"new ID\",\"content\":[{\"id\":\"50e0300a-6668-42b3-a474-81a6a08f773f\"},{\"id\":\"f0bee3f3-2c40-4b44-8608-a6fedb226b7a\"}],\"data\":\"AAAAAAAA\"}";
//when
Type type = new TypeToken<Container<Record>>() {
}.getType();
Container<Record> containerRecord = Container.deserializeType(json, type);
//then
assertEquals("50e0300a-6668-42b3-a474-81a6a08f773f", containerRecord.content.get(0).id);
assertEquals("f0bee3f3-2c40-4b44-8608-a6fedb226b7a", containerRecord.content.get(1).id);
}
@Test
public void testRecord() {
//given
String json = "{\"id\":\"new ID\",\"content\":[{\"id\":\"50e0300a-6668-42b3-a474-81a6a08f773f\"},{\"id\":\"f0bee3f3-2c40-4b44-8608-a6fedb226b7a\"}],\"data\":\"AAAAAAAA\"}";
//when
ContainerRecord containerRecord = new Gson().fromJson(json, ContainerRecord.class);
//then
assertEquals("50e0300a-6668-42b3-a474-81a6a08f773f", containerRecord.content.get(0).id);
assertEquals("f0bee3f3-2c40-4b44-8608-a6fedb226b7a", containerRecord.content.get(1).id);
}
@Test
public void testRecordWithType() {
//given
String json = "{\"id\":\"new ID\",\"content\":[{\"id\":\"50e0300a-6668-42b3-a474-81a6a08f773f\"},{\"id\":\"f0bee3f3-2c40-4b44-8608-a6fedb226b7a\"}],\"data\":\"AAAAAAAA\"}";
//when
Type type = new TypeToken<Container<Record>>() {
}.getType();
Container<Record> containerRecord = new Gson().fromJson(json, type);
//then
assertEquals("50e0300a-6668-42b3-a474-81a6a08f773f", containerRecord.content.get(0).id);
assertEquals("f0bee3f3-2c40-4b44-8608-a6fedb226b7a", containerRecord.content.get(1).id);
}
@Test
public void testContainerString() {
//given
String json = "{\"id\":\"new ID\",\"content\":[\"37c84304-ab80-4f92-8b2a-710b362ecb3f\"],\"data\":\"AAAAAAAA\"}";
//when
Type type = new TypeToken<Container<String>>() {
}.getType();
Container<String> containerRecord = new Gson().fromJson(json, type);
//then
assertEquals("37c84304-ab80-4f92-8b2a-710b362ecb3f", containerRecord.content.get(0));
}
}
我的class记录
public class Record {
public String id;
}
和我的容器
public class ContainerRecord extends Container<Record> {
}
和容器
public class Container<T> {
public String id;
public List<T> content;
public Object data;
public static <T> Container<T> deserializeClass(String json, Class<? extends Container<T>> type) {
return new Gson().fromJson(json, type);
}
public static <T> Container<T> deserializeType(String json, Type type) {
return new Gson().fromJson(json, type);
}
public static <T> Container<T> deserialize(String json, Class<T> clazz) {
Type type = TypeToken.getParameterized(Container.class,clazz).getType();
return new Gson().fromJson(json, type);
}
}
使用 Gson
反序列化参数化 class Container<T>
的对象,导致 T
的某些值的 java.lang.ClassCastException
,例如对于由 String
和 List<String>
字段组成的简单 Record
类型:
com.google.gson.internal.LinkedTreeMap cannot be cast to Record
有趣的是,相同的代码在内联调用 fromJson()
方法时有效,即以下语句 return 一个有效值:
Container<Record> value = new Gson().fromJson(
json, new TypeToken<Container<Record>>(){}.getType());
Container<T>
的定义也很简单:
public class Container<T> {
private static final Gson PARSER = new Gson();
private String id;
private List<T> content;
private Object data;
public static <T> Container<T> deserialize(String json, Class<T> type) {
return PARSER.fromJson(json, new TypeToken<Container<T>>(){}.getType());
}
}
将 deserialize()
方法更改为非静态方法无法解决问题。
有什么想法吗?
你想要 ParameterizedType 我的解决方案是创建
public static <T> Container<T> deserialize(String json, Class<T> clazz) {
Type type = TypeToken.getParameterized(Container.class,clazz).getType();
return new Gson().fromJson(json, type);
}
问题是 T,因为 Java 不知道我的类型并生成 T 的类型
public static <T> Container<T> sec(String json, Class<T> clazz) {
Type type1 = new TypeToken<Container<T>>() { }.getType();
Type type = TypeToken.getParameterized(Container.class,clazz).getType();
System.out.println(type1); //==>pl.jac.container.Container<T>
System.out.println(type); //==>pl.jac.container.Container<pl.jac.container.Record>
return new Gson().fromJson(json, type);
}
这是测试更多示例以更正 运行 测试 testContainerRecord2 是针对你的问题
import java.lang.reflect.Type;
import org.junit.Test;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import static org.junit.Assert.assertEquals;
public class ContainerTest {
@Test
public void testContainerRecord() {
//given
String json = "{\"id\":\"new ID\",\"content\":[{\"id\":\"50e0300a-6668-42b3-a474-81a6a08f773f\"},{\"id\":\"f0bee3f3-2c40-4b44-8608-a6fedb226b7a\"}],\"data\":\"AAAAAAAA\"}";
//when
Container<Record> containerRecord = Container.deserializeClass(json, ContainerRecord.class);
//then
assertEquals("50e0300a-6668-42b3-a474-81a6a08f773f", containerRecord.content.get(0).id);
assertEquals("f0bee3f3-2c40-4b44-8608-a6fedb226b7a", containerRecord.content.get(1).id);
}
@Test
public void testContainerRecord2() {
//given
String json = "{\"id\":\"new ID\",\"content\":[{\"id\":\"50e0300a-6668-42b3-a474-81a6a08f773f\"},{\"id\":\"f0bee3f3-2c40-4b44-8608-a6fedb226b7a\"}],\"data\":\"AAAAAAAA\"}";
//when
Container<Record> containerRecord = Container.deserialize(json, Record.class);
//then
assertEquals("50e0300a-6668-42b3-a474-81a6a08f773f", containerRecord.content.get(0).id);
assertEquals("f0bee3f3-2c40-4b44-8608-a6fedb226b7a", containerRecord.content.get(1).id);
}
@Test
public void testGenericWithType() {
//given
String json = "{\"id\":\"new ID\",\"content\":[{\"id\":\"50e0300a-6668-42b3-a474-81a6a08f773f\"},{\"id\":\"f0bee3f3-2c40-4b44-8608-a6fedb226b7a\"}],\"data\":\"AAAAAAAA\"}";
//when
Type type = new TypeToken<Container<Record>>() {
}.getType();
Container<Record> containerRecord = Container.deserializeType(json, type);
//then
assertEquals("50e0300a-6668-42b3-a474-81a6a08f773f", containerRecord.content.get(0).id);
assertEquals("f0bee3f3-2c40-4b44-8608-a6fedb226b7a", containerRecord.content.get(1).id);
}
@Test
public void testRecord() {
//given
String json = "{\"id\":\"new ID\",\"content\":[{\"id\":\"50e0300a-6668-42b3-a474-81a6a08f773f\"},{\"id\":\"f0bee3f3-2c40-4b44-8608-a6fedb226b7a\"}],\"data\":\"AAAAAAAA\"}";
//when
ContainerRecord containerRecord = new Gson().fromJson(json, ContainerRecord.class);
//then
assertEquals("50e0300a-6668-42b3-a474-81a6a08f773f", containerRecord.content.get(0).id);
assertEquals("f0bee3f3-2c40-4b44-8608-a6fedb226b7a", containerRecord.content.get(1).id);
}
@Test
public void testRecordWithType() {
//given
String json = "{\"id\":\"new ID\",\"content\":[{\"id\":\"50e0300a-6668-42b3-a474-81a6a08f773f\"},{\"id\":\"f0bee3f3-2c40-4b44-8608-a6fedb226b7a\"}],\"data\":\"AAAAAAAA\"}";
//when
Type type = new TypeToken<Container<Record>>() {
}.getType();
Container<Record> containerRecord = new Gson().fromJson(json, type);
//then
assertEquals("50e0300a-6668-42b3-a474-81a6a08f773f", containerRecord.content.get(0).id);
assertEquals("f0bee3f3-2c40-4b44-8608-a6fedb226b7a", containerRecord.content.get(1).id);
}
@Test
public void testContainerString() {
//given
String json = "{\"id\":\"new ID\",\"content\":[\"37c84304-ab80-4f92-8b2a-710b362ecb3f\"],\"data\":\"AAAAAAAA\"}";
//when
Type type = new TypeToken<Container<String>>() {
}.getType();
Container<String> containerRecord = new Gson().fromJson(json, type);
//then
assertEquals("37c84304-ab80-4f92-8b2a-710b362ecb3f", containerRecord.content.get(0));
}
}
我的class记录
public class Record {
public String id;
}
和我的容器
public class ContainerRecord extends Container<Record> {
}
和容器
public class Container<T> {
public String id;
public List<T> content;
public Object data;
public static <T> Container<T> deserializeClass(String json, Class<? extends Container<T>> type) {
return new Gson().fromJson(json, type);
}
public static <T> Container<T> deserializeType(String json, Type type) {
return new Gson().fromJson(json, type);
}
public static <T> Container<T> deserialize(String json, Class<T> clazz) {
Type type = TypeToken.getParameterized(Container.class,clazz).getType();
return new Gson().fromJson(json, type);
}
}