2012-06-25 25 views
4

我嘗試使用gson庫來反序列化發送給我的對象流。 在我看到的所有例子中,當調用Json的方法時,我們已經知道我們期望擁有什麼類型的對象。GSON反序列化:如何知道對象?

在我的情況下,我收到一個不同的對象流,我想知道在反序列化它們之前知道對象類的最佳方法。

{ A : {...}, B : { B1 : {...}, B2 : {...} }, C : {...} } 

在這個例子中,我想有辦法知道,3個對象已經發給我:的A.class,B.class和C.class

感謝

回答

6

The documentation包含使用任意類或兩次傳遞的反序列化示例(集合中的第一個一般反序列化,然後是內容反序列化)。

This exemple看起來完全像你所需要的。你能適應它使用

JsonObject obj = parser.parse(json).getAsJsonObject(); 

獲得JsonObject不是數組,這樣你就可以遍歷(使用entrySet)的所有特性,並通過簡單的映射名稱類根據名稱(a = gson.fromJson(myjsonelement, A.class);)反序列化。

+0

謝謝JsonArray好像我需要什麼。我明天再試。謝謝 –

2

是的,我也偶然發現了這個問題。 gson無法找出字段值的實際類別。它只是嘗試實例化用於定義字段的類。不用說,它通常不是我們想要的。 所以,如果你有,說

class C { 
    private A a; 
    private A c; 
} 

class B extends A { 
} 

然後在運行時,你

C c; 
c.a = new B(); 
c.c = new B(); 

deserialisation後,你得到的是

c.a.getClass()==A.class; 
c.b.getClass()==A.class; 

,所以你必須明確指定的子類。這是一個gson友好的包裝類。

public class S<T> { 
    private String objectClass; 
    private String rawObjectRepresentation; 
    // Gson needs no args constructor 
    public S() { 
    } 

    public S(T obj) { 
     objectClass = obj.getClass().getName(); 
     rawObjectRepresentation = getGson().toJson(obj); 
    } 

    @SuppressWarnings("unchecked") 
    public T extract() throws ClassNotFoundException { 
     final Class<?> clazz = Class.forName(objectClass); 
     return (T)getGson().fromJson(rawObjectRepresentation, clazz); 
    } 

    private Gson getGson() { 
     return new GsonBuilder().create(); 
    } 

    @Override 
    public String toString() { 
     return "type:"+objectClass; 
    } 
} 
2

如果JSON對象,你可以用它來識別你需要使用的子類中的字段,那麼你可以用火GSON:https://github.com/julman99/gson-fire

它有一個叫做類型選擇功能,正是你所需要的。

試想一個基類和兩個子類,A和B,然後代碼是這樣的:

GsonFireBuilder builder = new GsonFireBuilder() 
    .registerTypeSelector(Base.class, new TypeSelector<Base>() { 
     @Override 
     public Class<? extends Base> getClassForElement(JsonElement readElement) { 
      String kind = readElement.getAsJsonObject().get("kind").getAsString(); 
      if(kind.equals("a")){ 
       return A.class; //This will cause Gson to deserialize the json mapping to A 
      } else if(kind.equals("b")) { 
       return B.class; //This will cause Gson to deserialize the json mapping to B 
      } else { 
       return null; //returning null will trigger Gson's default behavior 
      } 
     } 
    }); 
Gson gson = builder.createGson();