java - 忽略 RuntimeTypeAdapterFactory 中未注册的子类型
问题描述
我们有一个使用 GSON 作为转换器的 Retrofit API,它会调用要显示给用户的卡片列表。卡片遵循以下格式:
[
{
"cardType": "user",
"data": {}
},
{
"cardType": "content",
"data": {}
}
]
属性因卡而data
异,因此我们使用 GSON 来解决此问题RuntimeTypeAdapterFactory
:
final RuntimeTypeAdapterFactory<Card> factory = RuntimeTypeAdapterFactory
.of(Card.class, "cardType")
.registerSubtype(UserCard.class, "user")
...
.registerSubtype(ContentCard.class, "content");
但是,我们发现如果更新 API 以包含我们不期望的新cardType,这会默默地反序列化失败。我的意思是默默地response.isSuccessful()
返回true,但response.body()
为null。我们能够确定新卡类型的唯一方法是问题是通过反复试验。
有没有办法让 GSON 忽略我们尚未注册的任何 cardTypes?如果我们尝试添加这张新卡但应用程序不支持它,我想忽略它。
解决方案
我认为问题在于尝试为未注册的类型名称创建适配器时会引发异常(参见s 源代码的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);
}
...
}
这可能会导致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);
}
如果您能够返回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;
}
澄清一下,因为您现在返回null
而不是抛出,所以您的列表将包含此 null 元素。要真正忽略它,请确保您调用list.filterNotNull()
实现。
推荐阅读
- .net - 如何在 .Net 中使用 Confluent.Kafka 从特定的 TopicPartitionOffset 消费
- asp.net - 按钮未在母版页上的 div 内触发
- python - Databricks 文件系统 - 根据日期复制文件
- react-native - 当列表中有短暂的触摸时,onPress 立即在 ListItem 中触发
- c# - 我如何转换 IEnumerable
长 - html - 在 index file.html 中包含一些 html 代码
- python - 如何从熊猫数据框中的另一列创建列,如下所示
- c++ - 如何从 C++ 或 cocos2dx 中的表情符号中获取 unicode?
- python-3.x - python包中的requirements.txt
- macos - NSTextField 是否有 textField:shouldReplaceCharactersInRange 的等价物?