2013-08-05 144 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