Android: GSON 反序列化完成后的计算属性

Android: Compute properties after GSON deserialization finished

在我的一个应用程序中,我有一个通用的 Volley Web 服务,我用它从我们的服务器加载数据并像这样使用 GSON 反序列化它们:

@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
    try {
        String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        T parsedJson = mGson.fromJson(json, mType);
        return Response.success(parsedJson, HttpHeaderParser.parseCacheHeaders(response));
    } catch (Exception e) {
        return Response.error(new ParseError(e));
    }
}

现在我要反序列化的对象之一有点 特殊 因为它的 json 模型包含两个列表但在代码中我需要一个字典,其中 id第一个列表对象的键和第二个列表对象的数组是值。

我还需要在反序列化后对两个列表进行排序。 (我请求我们的后端开发人员进行排序并为我提供合适的 json 模型,但他们拒绝这样做,不要问我为什么...)。

无论如何,现在我需要一种方法来进行排序以及计算属性。

在 iOS 中,我使用的是 SwiftyJson,它并不是真正的自动 JSON 反序列化,你会从 GSON 获得,但我可以在后台线程中计算和排序必要的字段"deserialize" 对象。

不过,在 Android 上,我有这个通用函数,因此不知道我当前正在反序列化哪个对象,就我而言,GSON 使用默认构造函数并直接写入字段,而不是比使用二传手。

所以现在我卡住了。我想知道什么时候最好的情况是计算我的字段。我想过这些方法:

  1. 添加一个瞬态布尔值来检查我是否已经对列表进行了排序。当访问列表的 getter 时,第一次它是错误的,所以我知道我必须排序。我对列表进行排序,将排序后的列表存储回去,然后 return 它。对于计算字典,我只需要检查它是否为空,如果是,计算它
  2. 使用单一方法实现某种 PostDeserializable 接口。在通用 Web 服务中,我可以检查 T parsedJson 是否是该接口的实例,如果是,则调用它的方法。

后者的优势在于它会在后台 运行 但我还必须记住该界面(对于不了解它的新开发人员来说可能会有问题)。然而,第一个可能会产生影响,因为它很可能会在 UI 线程中 运行。

我想知道 GSON 中是否有默认方式来执行某些 post 序列化方法,也许是通过注释?希望你能帮我找到用最少的自定义代码的最佳方法。

好吧,显然没有默认的方法。虽然有一个与我在原始 post 中建议的接口类似的接口,但它只在 gson-extras 中可用,它不是通过 maven 发布的,所以不能简单地将它包含在 gradle 文件中.相反,人们必须手动下载它并使其保持最新。

对我来说,这似乎是不必要的工作,而且只为这个接口包含整个 gson-extras 似乎有点过头了。在测试了我的两种方法之后,我想我会坚持我建议的接口解决方案。

我将我的 JSON 截击基本请求(我所有的 JSON 请求都继承自该请求)更改为以下内容:

@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
    try {
        String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        T parsedJson = mGson.fromJson(json, mType);

        if (parsedJson instanceof PostDeserializable) {
            PostDeserializable postDeserializable = (PostDeserializable) parsedJson;
            postDeserializable.postDeserialization();
        }

        if (parsedJson instanceof Object[]) {
            Object[] array = (Object[]) parsedJson;
            for(Object value : array) {
                if (value instanceof PostDeserializable) {
                    PostDeserializable postDeserializable = (PostDeserializable) value;
                    postDeserializable.postDeserialization();
                }
            }
        }

        return Response.success(parsedJson, HttpHeaderParser.parseCacheHeaders(response));
    } catch (Exception e) {
        return Response.error(new ParseError(e));
    }
}

PostSerializable 接口看起来也很简单:

public interface PostDeserializable {
    void postDeserialization();
}

要使用它,我所要做的就是在我的模型 POJO 上实现它。请注意,我检查 T parsedJson 本身是否是我的接口的一个实例,以及我检查它是否是一个数组,如果是,则数组中的对象是否属于该类型。

对我来说这就足够了,因为如果顶级对象是 PostSerializable 的实例或者顶级对象是 PostSerializable 的数组,我只需要一个 PostSerializable。

这不是通用解决方案,因为它不包括 PostSerializable 在另一个模型的第二层中的情况。

在这种情况下,我认为使用 gson-extras 肯定是有意义的。