我们有一个将GSON用作转换器的Retrofit API,它要求将卡片列表显示给用户.卡遵循以下格式:
[ { "cardType": "user", "data": {} }, { "cardType": "content", "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忽略我们尚未注册的任何cardType?如果我们尝试添加此新卡,但应用程序不支持该卡,则我想忽略它.
解决方法:
我认为问题是由于以下事实造成的:RuntimeTypeAdapterFactory在尝试为未注册的类型名称创建适配器时将引发异常(请参见RuntimeTypeAdapterFactorys源代码的摘录):
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().
总结以上是内存溢出为你收集整理的java-忽略RuntimeTypeAdapterFactory中未注册的子类型全部内容,希望文章能够帮你解决java-忽略RuntimeTypeAdapterFactory中未注册的子类型所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)