Gson ClassCastException(LinkedTreeMap)

Gson ClassCastException (LinkedTreeMap)

使用 Gson 反序列化参数化 class Container<T> 的对象,导致 T 的某些值的 java.lang.ClassCastException,例如对于由 StringList<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);
    }
}