Ada*_*331 4 java android json gson retrofit
我们有一个使用 GSON 作为转换器的 Retrofit API,它会调用要向用户显示的卡片列表。卡片遵循以下格式:
[
{
"cardType": "user",
"data": {}
},
{
"cardType": "content",
"data": {}
}
]
Run Code Online (Sandbox Code Playgroud)
卡之间的属性data有所不同,因此为了解决这个问题,我们使用 GSON 的RuntimeTypeAdapterFactory:
final RuntimeTypeAdapterFactory<Card> factory = RuntimeTypeAdapterFactory
.of(Card.class, "cardType")
.registerSubtype(UserCard.class, "user")
...
.registerSubtype(ContentCard.class, "content");
Run Code Online (Sandbox Code Playgroud)
但是,我们发现,如果 API 更新为包含我们不期望的新卡类型,则反序列化会默默失败。我所说的默默地,response.isSuccessful()仍然返回true,但response.body()为null。我们能够确定新卡类型的唯一方法是通过反复试验来解决问题。
有没有办法让 GSON 忽略我们尚未注册的任何卡类型?如果我们尝试添加这张新卡但应用程序不支持它,我想忽略它。
我认为问题是由于RuntimeTypeAdapterFactory尝试为未注册类型名称创建适配器时会抛出异常(请参阅RuntimeTypeAdapterFactory源代码摘录):
public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
...
// typeFieldName is the type name that is given when registering the sub type
if (jsonObject.has(typeFieldName)) {
throw new JsonParseException("cannot serialize " + srcType.getName()
+ " because it already defines a field named " + typeFieldName);
}
...
}
Run Code Online (Sandbox Code Playgroud)
这可能会导致Retrofit截断对 的整个响应null。
然后查看声明TypeAdapterFactory:
public interface TypeAdapterFactory {
/**
* Returns a type adapter for {@code type}, or null if this factory doesn't
* support {@code type}.
*/
<T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
}
Run Code Online (Sandbox Code Playgroud)
如果您能够返回null而不是抛出该异常,我想Retrofit可以返回它识别的所有子类。
RuntimeTypeAdapterFactory通过扩展和覆盖有问题的方法,这很容易处理,但不幸的是,类被声明为final.
因此,您可以创建一个包装类型适配器来调用其中的原始 RuntimeTypeAdapter,或者像我一样,只需将类的源代码复制RuntimeTypeAdapterFactory到您自己的某个包中,然后根据您的需要对其进行编辑。它是开源的。所以有问题的部分是这样的:
if (jsonObject.has(typeFieldName)) {
log.warn("cannot serialize " + srcType.getName()
+ " because it already defines a field named " + typeFieldName);
return null;
}
Run Code Online (Sandbox Code Playgroud)
澄清一下,因为您现在是返回null而不是抛出,所以您的列表将包含此 null 元素。要真正忽略它,请确保您调用list.filterNotNull()了实现。
| 归档时间: |
|
| 查看次数: |
1386 次 |
| 最近记录: |