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

Ant*_*ich 28 java android json gson

我得到一个有"场"字段的json.
如果"字段"有数据,那么有一个OBJECT有许多(大约20个)其他字段也是对象.我可以毫无问题地反序列化它们.
但是如果"field"没有数据,那么它就是一个空的ARRAY(我知道它很疯狂,但那是服务器的响应而我无法改变它).像这样的东西:

空的时候:

"extras":[

]
Run Code Online (Sandbox Code Playgroud)

有一些数据:

"extras": {
    "22":{ "name":"some name" },
    "59":{ "name":"some other name" },
    and so on...
}
Run Code Online (Sandbox Code Playgroud)

所以,当没有数据(空数组)时,我显然得到了异常

Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 4319
Run Code Online (Sandbox Code Playgroud)

我尝试使用自定义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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我通过以下方式阅读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);
Run Code Online (Sandbox Code Playgroud)

我不想手动反序列化所有20个字段(我知道这是一个选项),我只想调用context.defaultDeserialize()或类似的东西.
再一次:我没有任何问题反序列化普通的json,创建自定义对象,注册自定义TypeAdapter,自定义JavaDeserializers.这一切都已经有效了.我只需要一些处理数据的解决方案,可以是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;
                }
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

Joe*_*oey 23

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

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

以下是您可以使用的getDelegateAdapter示例.

  • +1 for getDelegateAdapter()这是一个实现通用功能的好方法,而与对象的类型无关。例如,在对象上调用反序列化后功能。 (2认同)

Rah*_*hul 13

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 问题在于,通常您会在Gson实例上拥有其他特殊的规则和适配器。这将创建一个新的默认规则,而无需您的应用特定规则 (3认同)