如何用gson调用默认的反序列化

我得到一个具有“字段”字段的JSON。
如果“字段”有数据,那么有一个OBJECT有许多(大约20个)也是对象的其他字段。 我可以反序列化他们没有任何问题。
但是,如果“字段”没有数据,它是一个空的ARRAY(我知道这是疯狂的,但这是从服务器的响应,我不能改变它)。 像这样的东西:

空时:

"extras":[ ] 

有一些数据:

 "extras": { "22":{ "name":"some name" }, "59":{ "name":"some other name" }, and so on... } 

所以,如果没有数据(空数组)的时候,我显然会得到exception

 Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 4319 

我试图使用自定义的JavaDeserializer:

 public class ExtrasAdapter implements JsonDeserializer<Extras> { @Override public Extras deserialize(JsonElement json, Type typeOf, JsonDeserializationContext context) throws JsonParseException { try { JsonObject jsonObject = json.getAsJsonObject(); // deserialize normally // the following does not work, as it makes recursive calls // to the same function //return context.deserialize(jsonObject, // new TypeToken<Object>(){}.getType()); } catch (IllegalStateException e) { return null; } } 

}

我以下面的方式阅读json

 Gson gsonDecoder = new GsonBuilder().registerTypeAdapter(Extras.class, new ExtrasAdapter(); // httpResponse contains json with extras filed. Reader reader = new InputStreamReader(httpResponse.getEntity().getContent()); Extras response = gsonDecoder.fromJson(reader, Extras.class); 

我不想反序列化所有20个字段手动(我知道这是一个选项),我只是想调用context.defaultDeserialize(),或类似的东西。
再一次:我没有反序列化普通的json,创build自定义对象,注册自定义TypeAdapter,自定义JavaDeserializers的任何问题。 这一切已经工作。 我只需要一些解决scheme来处理数据,可以是ARRAY和OBJECT。
谢谢你的帮助。

======================

乔伊的答案是完美的。 那是我正在寻找的东西。 我会在这里发布我的代码。

 public class SafeTypeAdapterFactory implements TypeAdapterFactory { public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type); return new TypeAdapter<T>() { public void write(JsonWriter out, T value) throws IOException { try { delegate.write(out, value); } catch (IOException e) { delegate.write(out, null); } } public T read(JsonReader in) throws IOException { try { return delegate.read(in); } catch (IOException e) { Log.w("Adapter Factory", "IOException. Value skipped"); in.skipValue(); return null; } catch (IllegalStateException e) { Log.w("Adapter Factory", "IllegalStateException. Value skipped"); in.skipValue(); return null; } catch (JsonSyntaxException e) { Log.w("Adapter Factory", "JsonSyntaxException. Value skipped"); in.skipValue(); return null; } } }; } 

}

Solutions Collecting From Web of "如何用gson调用默认的反序列化"

尝试使用GSON> = 2.2.1并查找TypeAdapterFactory类。

这将使您能够在反序列化之前检查对象并应用自定义代码,同时避免recursion。

这里是你可以使用的getDelegateAdapter的一个例子。

 public class ExtrasAdapter implements JsonDeserializer<Extras> { @Override public Extras deserialize(JsonElement json, Type typeOf, JsonDeserializationContext context) throws JsonParseException { try { JsonObject jsonObject = json.getAsJsonObject(); return new Gson().fromJson(jsonObject , Extras.class); // default deserialization } catch (IllegalStateException e) { return null; } } 

对于任何迟到的人,你不需要实现types适配器来解决这个问题,虽然这样做是完全有效的解决scheme。

这个问题的答案实际上是在原来的问题:

 public class ExtrasAdapter implements JsonDeserializer<Extras> { @Override public Extras deserialize(JsonElement json, Type typeOf, JsonDeserializationContext context) throws JsonParseException { try { JsonObject jsonObject = json.getAsJsonObject(); // deserialize normally // the following does not work, as it makes recursive calls // to the same function //return context.deserialize(jsonObject, new TypeToken<Object>(){}.getType()); } catch (IllegalStateException e) { return null; } } 

注释掉了

 return context.deserialize(jsonObject, new TypeToken<Object>(){}.getType()); 

几乎是解决scheme。 这个问题是双重的。 首先,jsonObject是最初传递给这个函数的确切对象。

 JsonObject jsonObject = json.getAsJsonObject(); 

所以传递给context.deserialize()将会创buildrecursion,最后是OOM。 这里的解决scheme是parsing出jsonObject中的对象。

这导致我们遇到第二个问题,就是这里有两件事情混杂在一起。 “Extras”是一个对象types,大概有一个支持它的具体类(可能是一个空数组)。 “额外”是一张地图。 试图parsing一个“额外”作为“额外”是不会工作的。 为此,我build议“附加”的定义如下:

 public class Extras { Map<String, Map<String, String>> extras; // you could also create a concrete class for "Extra" //and have this be a Map<String, Extra> } 

在这种情况下,使用context.deserialize解决问题变得微不足道。

正如我上面所说的,TypeAdatper对于这个问题是一个非常有效的解决scheme。 我只相信这比你需要的多。