2016-09-29 56 views
6

我正在使用GSON作为json反序列化器的应用程序,并且需要从REST API反序列化多态json。在解释mi问题注释之前,我已经在GSON中寻找多态反序列化并且已经成功地在几个案例中实现了它。所以这是我遇到的一个具体问题。在问这个问题之前,我也读过this great postthis stackoverflow discussion。顺便说一下,我使用RuntimeTypeAdapterFactory来反序列化多态对象。使用GSON抛出异常反序列化多态JSON

问题我有很明显GSON的RuntimeTypeAdapterFactory不允许声明指定层次结构内对象的类型的字段。我会用一些代码进一步解释。我有以下的POJO结构(POJO的已减少为简单起见):

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; 
} 

现在,这是我所定义的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":"[email protected]", 
     "name":"Albert" 
    } 
} 

我得到这个例外

com.google.gson.JsonParseException: cannot serialize com.mobile.model.entities.v2.common.User because it already defines a field named userType 

但是,如果我在BaseUser类更改属性 “的UserType” 的名字以“键入”例如,我反序列化相同的JSON一切正常。我不明白为什么GSON runtimTypeAdapterFactory有这个限制。实际上在this blog post显然这不是一个问题。

任何人都可以解释这里发生了什么,为什么定义类型的属性名称不能在pojos层次结构中定义?

编辑这个问题不是在反序列化时,而是在使用上述代码进行序列化时。在答案中找到进一步的解释。

+0

按照错误,你确定你没有宣布在'User'领域'userType'课也?它已经在'BaseUser'类中声明过了,所以不需要重新声明它。 –

+0

嗨Jyotman。不,我确定我没有两次声明字段usertype。它只在基本用户中声明。另外我在问题结束时说过,只要将字段userType的名称从BaseUser类更改为与json和RuntimeTypeAdapterFactory中声明的内容不同的内容,反序列化就可以正常工作。但是,谢谢你的建议! – JorgeMuci

回答

4

那么,经过一段时间的挖掘,我发现问题实际上并不是反序列化,问题出现在序列化和如问题中所述注册RuntimeTypeFactory时。如果您注册一个runtimeTypeAdapterFactory并使用相同的字段名在工厂和在你的POJO定义类的类型,从序列化的POJO生成的JSON使用GSON与RuntimeTypeAdapterFactory的SpecialUser到JSON例如将是:

{ 
    "user":{ 
     "userType":"SPECIAL", 
     "email":"[email protected]", 
     "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 

因为去外地用户类型重复的JSON由于GSON串行器,如该类BaseUser注册的RuntimeTypeAdapterFactory宣布,它会自动添加一个字段。

1

我觉得用自己的用户类型,而不@expose注释会做的伎俩

Regads