2013-08-05 191 views
2

數組我想反序列化複雜的對象GSON反序列化複雜的對象

例如數組我有對象MyTestObject

public class MyTestObject{ 

    String param1; 
    String param2; 
    int param3; 
} 

現在我有對象的數組命名MyTestObject

和我的json看起來像這樣

{ 
[ 
"param1":"something1", 
"param2:"something2", 
"param3":3 
], 
[ 
"param1":"something1", 
"param2:"something2", 
"param3":3 
], 
[ 
"param1":"something1", 
"param2:"something2", 
"param3":3 
] 
} 

這是我desearilization

public static <T> List<T> fromJSON(String json, Class<T> className) { 
    GsonBuilder builder = new GsonBuilder(); 
    builder.serializeNulls(); 
    Type myType = new TypeToken<List<T>>() { 
    }.getType(); 
    Gson g1 = builder.create(); 
    List<T> objects = (List<T>) g1.fromJson(json, (Type) myType); 
    for (T object : objects) { 
     Log.d(TAG, "object: " + object + " class " + object.getClass()); 
    } 
    return objects; 
} 

ArrayList<MyTestObject> objects = fromJSON(myjson,MyTestObject.class); 

代碼數組本身被反序列化正確的,但是,它裏面的對象是一個正確的類一樣,他們是類型com.google.gson.internal.LinkedTreeMap

,當我需要他們的類型MyTestObject

我該如何解決這個問題?

+0

這可能有助於http://stackoverflow.com/questions/17231298/serializing-a-sparsearrayt-with-gson – Tala

+1

這不是有效的JSON!你不能擁有這個'{[...],[......]}',但是你需要這個'{'foo':[']'bar':[。 ..],'baz':[...]}'...我的意思是,根對象中的數組必須有一個名稱... – MikO

回答

3

樣本:

public class Test<T> { 
    public static void main(String[] args) throws Exception { 
    new Test<String>().test(String.class); 
    new Test<Integer>().test(Integer.class); 
    new Test<Long>().test(Long.class); 
    } 

    public void test(Class<T> cls) throws Exception { 
    TypeToken<?> typeOfT = getGenToken(List.class, cls); 
    List<?> lst = (List<?>) new Gson().fromJson("[1, 2, 3]", typeOfT.getType()); 

    for (Object o : lst) { 
     System.out.println("value : " + o + ", type : " + o.getClass()); 
    } 
    } 

    static TypeToken<?> getGenToken(final Class<?> raw, final Class<?> gen) throws Exception { 
    Constructor<ParameterizedTypeImpl> constr = ParameterizedTypeImpl.class.getDeclaredConstructor(Class.class, Type[].class, Type.class); 
    constr.setAccessible(true); 
    ParameterizedTypeImpl paramType = constr.newInstance(raw, new Type[] { gen }, null); 

    return TypeToken.get(paramType); 
    } 
} 

ParameterizedTypeImpl來自sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl

輸出:

value : 1, type : class java.lang.String 
value : 2, type : class java.lang.String 
value : 3, type : class java.lang.String 
value : 1, type : class java.lang.Integer 
value : 2, type : class java.lang.Integer 
value : 3, type : class java.lang.Integer 
value : 1, type : class java.lang.Long 
value : 2, type : class java.lang.Long 
value : 3, type : class java.lang.Long 

注:實際上我們可以用T取代wildcar,但是我們在這裏不會有用。

+0

hm,android沒有Oracle JVM函數,你有不同的方法來執行'ParameterizedTypeImpl'嗎? – CQM

+0

你可以嘗試自己實現'ParameterizedTypeImpl',只需複製/粘貼Sun類的代碼,就可以輕鬆地谷歌源代碼 – PomPom

1

你不能使用new TypeToken<List<T>>(),因爲類型擦除GSon將不知道T的類型。 https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Generic-Types

您可以提供以靜態方式T

Type myType = new TypeToken<List<Something>>() { 
}.getType(); 

或建立一個TypeTokenClass<T> VAR爲通用。據我所知,沒有簡單的方法可以做到這一點。這就是我要做的事:

static TypeToken<?> getGenToken(final Class<?> raw, final Class<?> gen) throws Exception { 
    Constructor<ParameterizedTypeImpl> constr = ParameterizedTypeImpl.class.getDeclaredConstructor(Class.class, Type[].class, Type.class); 
    constr.setAccessible(true); 
    ParameterizedTypeImpl paramType = constr.newInstance(raw, new Type[] { gen }, null); 

    return TypeToken.get(paramType); 
    } 

然後你就可以建立令牌是這樣的:

Class<T> tClass = ...; 
Type myType = new getGenToken<List.class, tClass>() 
+0

我得到noDechMethodException getDeclaredConstructor –

+0

奇怪。哪個Gson版本?你看到了什麼構造函數? 'System.out.println(Arrays.toString(ParameterizedTypeImpl.class.getDeclaredConstructors()));' – PomPom

+0

另外,我提供的方法只允許返回'ParameterizedType'的一個實例。如果你想要的話,你可以提取'$ Gson $ Types'中的'ParameterizedTypeImpl'(這是靜態私有的final)並且公開它。 – PomPom