【问题标题】:GSON deserialize an array of complex objectsGSON 反序列化复杂对象数组
【发布时间】:2013-08-05 09:43:19
【问题描述】:

我想反序列化一个复杂对象的数组

例如我有对象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
]
}

这是我的去串化代码

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 类型时

我该如何解决这个问题?

【问题讨论】:

  • 这不是有效的 JSON!你不能有这个{[...], [...], [...]},但你需要这个{'foo':[...], 'bar':[...], 'baz':[...]}...我的意思是,根对象中的数组必须有一个名字...

标签: java gson arrays


【解决方案1】:

一个样本:

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,但这在这里没有用。

【讨论】:

  • hm,android没有Oracle JVM功能,你有什么不同的方法ParameterizedTypeImpl吗?
  • 您可以尝试自己实现ParameterizedTypeImpl,只需复制/粘贴Sun类的代码,即可轻松google源码
【解决方案2】:

您不能使用new TypeToken&lt;List&lt;T&gt;&gt;(),因为类型擦除GSon 不会知道T 的类型。 https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Generic-Types

您可以以静态方式提供Tlike

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

或者为泛型构建一个带有Class&lt;T&gt; var 的TypeToken。据我所知,没有简单的方法可以做到这一点。我就是这样做的:

 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>()

【讨论】:

  • 我在 getDeclaredConstructor 上得到 noSuchMethodException
  • 奇怪。哪个Gson版本?你看到了什么构造函数? System.out.println(Arrays.toString(ParameterizedTypeImpl.class.getDeclaredConstructors()));
  • 我提供的方法也只允许返回一个ParameterizedType 的实例。如果您愿意,您可以提取位于$Gson$TypesParameterizedTypeImpl(静态私有最终)并将其公开。
  • 你能给我一个工作的例子吗?我正在为此奋斗 2 天,我有一个 josn 数组,里面装满了所有相同类型的 json 对象,如果我单独反序列化每个对象,它们很好,如果我尝试从数组中提取它们......问题,奇怪的是,有一个json数组作为对象中的参数之一,它是一个差异类,它被反序列化就好了,这就是为什么我认为这也可以工作,但我不明白为什么没有
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-12
  • 2018-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多