我正在开发一个使用Gson作为JSON反序列化器的应用程序,需要从REST API反序列化多态JSON。在解释mi问题之前,我已经一直在寻找Gson的多态反序列化,并在几个案例中成功实现了它。所以这是我遇到的一个具体问题。在询问此问题之前,我还阅读了this great post和this Stack Overflow discussion。我顺便使用RuntimeTypeAdapterFactory
来反序列化多态对象。
我遇到的问题显然是GSON RuntimeTypeAdapterFactory
不允许声明指定内部对象类型的字段层次结构。我将用一些代码进一步解释。我有以下pojos结构(pojos为了简单起见已经减少了):
public abstract class BaseUser {
@Expose
protected EnumMobileUserType userType;
}
public class User extends BaseUser {
@Expose
private String name;
@Expose
private String email;
}
public class RegularUser extends User {
@Expose
private String address;
}
public class SpecialUser extends User {
@Expose
private String promoCode;
}
现在,这是我为User层次结构定义RuntimeTypeAdapterFactory
的代码。
public static RuntimeTypeAdapterFactory<BaseUser> getUserTypeAdapter() {
return RuntimeTypeAdapterFactory
.of(BaseUser.class, "userType")
.registerSubtype(User.class, EnumMobileUserType.USER.toString())
.registerSubtype(RegularUser.class, EnumMobileUserType.REGULAR.toString())
.registerSubtype(SpecialUser.class, EnumMobileUserType.SPECIAL.toString());
}
public static Gson getGsonWithTypeAdapters() {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapterFactory(getUserTypeAdapter());
return builder.create();
}
现在,当我尝试反序列化JSON文本时:
{
"user":{
"userType":"USER",
"email":"albert@gmail.com",
"name":"Albert"
}
}
我得到了这个例外:
com.google.gson.JsonParseException: cannot serialize com.mobile.model.entities.v2.common.User because it already defines a field named userType
但是,如果我更改属性的名称&#34; userType&#34;在我的BaseUser
课程中输入&#34;输入&#34;例如,我反序列化相同的JSON一切正常。我不明白Gson RuntimeTypeAdapterFactory
有这个限制的原因。事实上在this blog post显然这不是问题。
任何人都可以解释这里发生了什么,为什么不能在pojos层次结构中定义定义类型的属性的名称?
编辑问题不在反序列化时,而是在使用上述代码进行序列化时。在答案中找到进一步的解释。
答案 0 :(得分:7)
好吧,经过一段时间的挖掘,我发现问题实际上并没有反序列化,问题来自于序列化并按照问题中的描述注册了RuntimeTypeFactory。如果您注册了一个runtimeTypeAdapterFactory并使用相同的字段名称来定义工厂和pojo中的类类型,那么使用GSON将pojo序列化为json以及特殊用户的RuntimeTypeAdapterFactory所产生的json将是:
{
"user":{
"userType":"SPECIAL",
"email":"albert@gmail.com",
"name":"Albert"
"userType":"SPECIAL"
}
}
这将导致描述的异常:
com.google.gson.JsonParseException: cannot serialize com.mobile.model.entities.v2.common.User because it already defines a field named userType
因为GSON序列化器会在json中重复de field userType,它将自动添加在为BaseUser类注册的RuntimeTypeAdapterFactory中声明的字段。
答案 1 :(得分:2)
我认为使用你自己的没有@Expose注释的userType就可以了解
Regads
答案 2 :(得分:0)
您始终可以使用默认Gson实例进行 serialize (新Gson()),然后使用RuntimeTypeAdapterFactory实例进行 deserialize 。
如果要转换所有内容,建议不要使用@Expose。只会用多余的注释炸毁您的模型类。