2012-04-08 16 views
9

的我有这样的代码片段:GSON转换,而不是到的LinkedHashMap我的对象

public abstract class Repository<Entity extends BaseObject> { 

... 

public void readFromJson(){ 
    String content = "JSON content here"; 
    Gson gson = new Gson(); 
    Type entityType = new TypeToken<JSONObject<Entity>>(){}.getType(); 

    jsonObject = gson.fromJson(content, entityType); 

    for (Entity ent : jsonObject.getEntities()) ; 
    } 
} 

当我尝试做的foreach我的实体对象不再是实体类型,但LinkedHashMap的,我得到这个异常:JAVA .lang.ClassCastException:java.util.LinkedHashMap中不能转换到com.tranca.bookstore.domain.shared.BaseObject

这里是的JSONObject类(由我创建)

public class JSONObject<Entity> { 

private List<Entity> entities = new ArrayList<Entity>(); 
private long lastId = -1; 
public List<Entity> getEntities() { 
    return entities; 
} 
public void setEntities(List<Entity> entities) { 
    this.entities = entities; 
} 
public long getLastId() { 
    return lastId; 
} 
public void setLastId(long lastId) { 
    this.lastId = lastId; 
} 

public void incrementLastId() { 
    this.lastId++; 
} 

}

也许基本对象是相关的,所以我会在这里把代码:

public abstract class BaseObject implements Serializable { 

protected long id = (long) -1; 
protected int version = 0; 

protected BaseObject(){} 

public long getId() { 
    return id; 
} 
public void setId(long id) { 
    this.id = id; 
} 
public int getVersion() { 
    return version; 
} 
public void setVersion(int version) { 
    this.version = version; 
} 

} 
+0

您使用的是Gson 2.1吗? – 2012-04-09 13:56:55

回答

1

终于拿到了!

的问题是:

新TypeToken <的JSONObject <实体>>(){}的getType();

返回的JSONObject <的类型T>不是被延伸库子类的特定实体(例如UserRepository延伸库<用户>)。

诀窍是创建一个抽象方法来强制子类设置反序列化的类型。

总之,如果你得到这个错误,确保你有正确类型的类(如果你使用子类,确保它返回的是你的子类的类型而不是超类)。

+6

对不起,我遇到了同样的问题,但我不明白你的答案,请你澄清一下?谢谢! – 2012-04-21 06:17:24

+1

@JonathanLeung:如果我理解正确,问题是表达式'new TypeToken >(){}'的每次执行都会实例化一个匿名类的实例。 'Entity'实际上不是一个类,它只是'Repository'的一个类型参数,所以它在这个时候被完全擦除,甚至不能真正反映。 ('TypeToken'东西使用反射来检查类层次结构以绕过擦除,但当类本身引用类型参数时它不起作用。) – ruakh 2013-11-27 08:18:17

+1

对不起。你的答案再次不清楚。如果你能提供有意义的解决方案,那将是一件好事。 – 2014-11-25 11:53:30

3

我有相同/类似的问题。为了给出一个更明确的答案稍有不同的上下文:

我曾跟随其产生的误差“com.google.gson.internal.LinkedTreeMap不能转换为MyType的”制法:我想

/** 
    * Reads a LinkedHashMap from the specified parcel. 
    * 
    * @param <TKey> 
    *   The type of the key. 
    * @param <TValue> 
    *   The type of the value. 
    * @param in 
    *   The in parcel. 
    * @return Returns an instance of linked hash map or null. 
    */ 
    public static <TKey, TValue> LinkedHashMap<TKey, TValue> readLinkedHashMap(Parcel in) { 
    Gson gson = JsonHelper.getGsonInstance(); 
    String content = in.readString(); 
    LinkedHashMap<TKey, TValue> result = gson.fromJson(content, new TypeToken<LinkedHashMap<TKey, TValue>>(){}.getType()); 
    return result; 
    } 

一种简单的通用方式来读/写链接的hashmap。上述解决方案不起作用,因为根据我的理解,编译后会丢失带有TKey和TValue的TypeToken的类型信息。这就是问题所在。如果您将代码更改为以下示例,那么它就可以工作,因为现在我们明确定义了类型标记。我没有那么多的java,我明白为什么在这种情况下可以在运行时读取类型信息。

/** 
    * Reads a LinkedHashMap from the specified parcel. 
    * 
    * @param <TKey> 
    *   The type of the key. 
    * @param <TValue> 
    *   The type of the value. 
    * @param in 
    *   The in parcel. 
    * @return Returns an instance of linked hash map or null. 
    */ 
    public static <TKey, TValue> LinkedHashMap<TKey, TValue> readLinkedHashMap(Parcel in, TypeToken<LinkedHashMap<TKey, TValue>> typeToken) { 
    Gson gson = JsonHelper.getGsonInstance(); 
    Type type = typeToken.getType(); 
    String content = in.readString(); 
    LinkedHashMap<TKey, TValue> result = gson.fromJson(content, type); 
    return result; 
    } 

而现在只需要调用上面的函数:

readLinkedHashMap(in, new TypeToken<LinkedHashMap<UUID, MyObject>>(){}); 

旁注1:当writign链接的哈希地图,你不需要指定任何类型的令牌。 toJson(地图)就足够了。

旁注2(对我有问题):默认情况下,gson使用toString()来序列化密钥。如果您为可能是更复杂类型的密钥类型注册类型适配器,则在序列化时不应用此类型适配器,但在反序列化时应用此类适配器。这导致了一个不一致的,因此失败的过程。以下选项激活complex map key serialization

gsonBuilder.enableComplexMapKeySerialization() 
+1

主要是'gsonBuilder.enableComplexMapKeySerialization()'解决了我的问题 – CrandellWS 2016-05-20 10:59:01

相关问题