11

我有这段代码:

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 时,我的实体对象不再是 Entity 类型,而是 LinkedHashMap 并且我得到了这个异常:java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to 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;
}

}
4

2 回答 2

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;
  }

我想要一种简单的通用方法来读/写链接的哈希图。上述解决方案不起作用,因为据我了解,编译后带有 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:编写链接哈希映射时,您根本不需要指定任何类型标记。toJson(map) 就足够了。

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

gsonBuilder.enableComplexMapKeySerialization()
于 2015-11-06T07:40:51.827 回答
2

终于明白了!

问题是:

新 TypeToken< JSONObject< Entity>>(){}.getType();

返回 JSONObject<T> 的类型,而不是扩展 Repository 的子类的特定实体(例如,UserRepository 扩展 Repository<User>)。

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

总之,如果您收到此错误,请确保您拥有正确的类类型(如果您使用子类,请确保它返回您的子类而不是超类的类型)。

于 2012-04-09T21:33:40.383 回答