GSON转换为LinkedHashMap而不是我的对象

时间:2012-04-08 23:37:08

标签: java gson

我有这段代码:

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无法强制转换为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;
}

}

2 个答案:

答案 0 :(得分:3)

我有同样/类似的问题。在稍微不同的背景下给出更明确的答案:

我有以下方法产生错误&#34; com.google.gson.internal.LinkedTreeMap无法转换为MyType&#34;:

/**
   * 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:在写入链接的哈希映射时,您根本不需要指定任何类型的令牌。 toJson(地图)就足够了。

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

gsonBuilder.enableComplexMapKeySerialization()

答案 1 :(得分:2)

终于搞定了!

问题在于:

  

new TypeToken&lt;的JSONObject&LT;实体GT;&GT;(){}的getType();

返回JSONObject的类型&lt; T&GT;而不是扩展Repository的子类的特定实体(例如,UserRepository扩展了Repository&lt; User&gt;)。

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

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