【问题标题】:Android Retrofit + Realm + Gson: Serializer not calledAndroid Retrofit + Realm + Gson:未调用序列化程序
【发布时间】:2017-02-16 19:10:15
【问题描述】:

我的自定义序列化程序与 Retrofit、Realm 和 Gson 一起使用时遇到了一些问题。我在这里为我的三个类注册类型适配器:

GsonBuilder builder = new GsonBuilder();
        // Register type adapters to modify outgoing json according to server requirements.
        try {
            builder
                    .registerTypeAdapter(Class.forName("io.realm.UserProxy"), new UserSerializer())
                    .registerTypeAdapter(Class.forName("io.realm.FavoriteSongProxy"), new FavoriteSongSerializer())
                    .registerTypeAdapter(Class.forName("io.realm.ArtistProxy"), new ArtistSerializer())
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }

        Gson gson = builder.create();

        return new Retrofit.Builder()
                .baseUrl("http://10.0.3.2:8080/myUrl/rest/v1/")
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(httpClient.build())
                .build();

一个用户有一个FavoriteSong,一个FavoriteSong 有一个Artist。我的序列化器设置非常相似,这里是 FavoriteSongSerializer 的示例。

public class FavoriteSongSerializer implements JsonSerializer<FavoriteSong> {
    @Override
    public JsonElement serialize(FavoriteSong src, Type typeOfSrc, JsonSerializationContext context) {
        Log.v("qwer", "serializingFavoriteSong");
        final JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("id", src.getId());
        jsonObject.add("song", context.serialize(src.getSong()));
        return jsonObject;
    }

}

这是用户序列化程序:

public class UserSerializer implements JsonSerializer<User> {
    @Override
    public JsonElement serialize(User src, Type typeOfSrc, JsonSerializationContext context) {
        Log.v("qwer", "serializingUser");
        final JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("id", src.getId());
        jsonObject.add("favoriteSong", context.serialize(src.getFavoriteSong()));
        return jsonObject;
    }
}

奇怪的是,当我发送请求时,FavoriteSong 和 Song 序列化程序都会被调用(我可以看到日志语句),但 UserSerializer 没有。任何人都知道为什么会发生这种情况,或者我可以如何进行故障排除?

/** 编辑 **/

所以作为一个测试,我创建了一个只包含一个 id 的 TestModel,为它创建了一个序列化程序,注册了一个类型适配器,并将它添加到我的 User 模型中。而且它也无法调用TestModelSerializer(即使它根据默认方法进行序列化)。

【问题讨论】:

  • 我不熟悉领域,但问题可能是例如当您为类 io.realm.UserProxy 注册适配器时,UserSerializer 需要一个用户
  • 你检查过this answer吗?它提供了一种更简单的方法来解决 Gson+Realm 不兼容问题。
  • 不幸的是,这对我的具体问题没有帮助(我在下面找到了一个解决方案),但对于任何人的 Retrofit-Gson 问题,绝对可以指出这一点,我在几周内处理了同样的情况之前,花了一段时间才弄清楚发生了什么。

标签: android gson realm retrofit


【解决方案1】:

尝试使用registerTypeHierarchyAdapter 而不是registerTypeAdapter

.registerTypeHierarchyAdapter(Class.forName("io.realm.UserProxy"), new UserSerializer())

编辑:

 builder
     .setExclusionStrategies(new ExclusionStrategy() {
          @Override
          public boolean shouldSkipField(FieldAttributes f) {
              return f.getDeclaringClass().equals(RealmObject.class);
          }

          @Override
          public boolean shouldSkipClass(Class<?> clazz) {
              return false;
          }
      })
     .registerTypeAdapter(Class.forName("io.realm.UserProxy"), new UserSerializer())
     .registerTypeAdapter(Class.forName("io.realm.FavoriteSongProxy"), new FavoriteSongSerializer())
     .registerTypeAdapter(Class.forName("io.realm.ArtistProxy"), new ArtistSerializer())

【讨论】:

  • 我尝试了同样的结果。
  • 如果只注册UserSerializer,可以吗?请添加该序列化程序的代码
  • 我已经添加了用户序列化程序。我无法测试“仅”注册 User 序列化程序,因为由于 FavoriteSong 和 Song 引用而导致 gson 不合适。
  • 尝试颠倒 .registerTypeAdapter 调用的顺序,先注册歌曲和艺术家,再注册用户。
  • 是的,我也试过了,我注册类型适配器的顺序似乎并不重要。我将在一秒钟内更新我所做的问题中的几个故障排除步骤。
【解决方案2】:

所以如果将我的用户类型适配器注册为:

registerTypeAdapter(User.class, new UserSerializer())

代替:

.registerTypeAdapter(Class.forName("io.realm.UserProxy"), new UserSerializer())

调用用户序列化程序。我仍然不知道为什么,但它确实有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-04
    • 2017-01-08
    • 1970-01-01
    • 2016-03-17
    • 1970-01-01
    • 2017-02-19
    • 2015-11-04
    • 1970-01-01
    相关资源
    最近更新 更多