【问题标题】:Android: Compute properties after GSON deserialization finishedAndroid:GSON 反序列化完成后计算属性
【发布时间】:2017-06-08 13:40:40
【问题描述】:

在我的一个应用程序中,我有一个通用的 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,这并不是您从 GSON 获得的真正的自动 JSON 反序列化,但我可以在后台线程中计算和排序必要的字段,在该线程中我“反序列化”对象。

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

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

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

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

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

【问题讨论】:

  • 这看起来与我认为我需要的完全一样。不幸的是,这不能通过 gradle 获得,所以我想我可以只使用我自己的界面,这样我就没有其他 gson-extras 的所有开销
  • 是的,你是对的,这只是 gson-extras 并且不会作为工件在全球范围内发布。您可以借用该代码并对其进行修改以满足您的需求。

标签: android gson deserialization pojo


【解决方案1】:

好吧,显然没有默认的方法。虽然有一个与我在原始帖子中建议的界面类似的界面,但它仅在未通过 maven 发布的 gson-extras 中可用,因此不能简单地将其包含在 gradle 文件中。相反,您必须手动下载并保持最新状态。

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

我将我的 JSON volley 基本请求(我的所有 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 的一个实例,或者顶级对象是 PostSerializables 的数组,我每个人都需要 PostSerializable。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2018-04-02
    • 2013-03-07
    • 2015-05-11
    • 1970-01-01
    • 2021-05-26
    相关资源
    最近更新 更多