发布
社区首页 >问答首页 >用Gson抛出异常反序列化多态JSON

用Gson抛出异常反序列化多态JSON
EN

Stack Overflow用户
提问于 2016-09-29 08:43:57
回答 3查看 2.5K关注 0票数 14

我正在开发一个应用程序,它使用Gson作为JSON反序列化器,并需要从REST中反序列化多态JSON。在解释mi问题之前,请注意,我已经使用Gson查看了多态反序列化,并在一些情况下成功地实现了它。所以这是我要面对的一个特殊问题。在问这个问题之前,我还读过这个伟大的职位这个堆栈溢出的讨论。顺便说一下,我正在使用RuntimeTypeAdapterFactory反序列化多态对象。

,我遇到的问题是,显然GSON的RuntimeTypeAdapterFactory不允许声明字段,该字段指定层次结构中对象的类型。我会用一些代码进一步解释。我有以下pojos结构(为了简单起见,对pojos进行了简化):

代码语言:javascript
代码运行次数:0
复制
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的代码。

代码语言:javascript
代码运行次数:0
复制
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文本时:

代码语言:javascript
代码运行次数:0
复制
{  
   "user":{  
      "userType":"USER",
      "email":"albert@gmail.com",
      "name":"Albert"
   }
}

我明白这一例外:

代码语言:javascript
代码运行次数:0
复制
com.google.gson.JsonParseException: cannot serialize com.mobile.model.entities.v2.common.User because it already defines a field named userType

但是,如果我将BaseUser类中的属性“BaseUser”的名称更改为"type“,并且反序列化相同的JSON,一切都正常工作。我不明白为什么Gson RuntimeTypeAdapterFactory有这个限制。事实上,在这篇博客文章中,这显然不是一个问题。

有谁能解释一下这里发生了什么,为什么不能在pojos层次结构中定义定义类型的属性的名称?

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-10-05 07:15:01

经过一段时间的深入研究,我发现这个问题实际上并不是反序列化,而是在序列化和按照问题中描述的方式注册RuntimeTypeFactory时出现的。如果注册了一个runtimeTypeAdapterFactory并使用相同的字段名在工厂和pojo中定义了类类型,例如,通过RuntimeTypeAdapterFactory将pojo序列化为json的结果是:

代码语言:javascript
代码运行次数:0
复制
{  
  "user":{  
      "userType":"SPECIAL",
      "email":"albert@gmail.com",
      "name":"Albert"
      "userType":"SPECIAL"
  }
}

这将导致所述的例外情况:

代码语言:javascript
代码运行次数:0
复制
com.google.gson.JsonParseException: cannot serialize com.mobile.model.entities.v2.common.User because it already defines a field named userType

因为due由于GSON序列化程序而在json中重复,所以它将自动添加一个字段,该字段在为类BaseUser注册的RuntimeTypeAdapterFactory中声明。

票数 7
EN

Stack Overflow用户

发布于 2016-10-05 14:52:40

我认为在不使用@ userType注释的情况下使用自己的

雷吉德

票数 2
EN

Stack Overflow用户

发布于 2018-10-04 03:11:42

您可以始终使用默认的Gson实例来序列化(新的Gson()),然后使用RuntimeTypeAdapterFactory实例反序列化。

如果您希望转换所有内容,则建议不要使用@ want。它只会用多余的注释炸掉模型类。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39765516

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档