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 使用默认构造函数并直接写入字段,而不是比使用二传手。
所以现在我卡住了。我想知道什么时候最好的情况是计算我的字段。我想过这些方法:
- 添加一个瞬态布尔值来检查我是否已经对列表进行了排序。当访问列表的 getter 时,第一次它是错误的,所以我知道我必须排序。我对列表进行排序,将排序后的列表存储回去,然后 return 它。对于计算字典,我只需要检查它是否为空,如果是,计算它
- 使用单一方法实现某种
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 肯定是有意义的。
在我的一个应用程序中,我有一个通用的 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 使用默认构造函数并直接写入字段,而不是比使用二传手。
所以现在我卡住了。我想知道什么时候最好的情况是计算我的字段。我想过这些方法:
- 添加一个瞬态布尔值来检查我是否已经对列表进行了排序。当访问列表的 getter 时,第一次它是错误的,所以我知道我必须排序。我对列表进行排序,将排序后的列表存储回去,然后 return 它。对于计算字典,我只需要检查它是否为空,如果是,计算它
- 使用单一方法实现某种
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 肯定是有意义的。