java - 带有注解的 GSON 自定义序列化

标签 java android reflection annotations gson

我有一个使用 GSON 进行自定义序列化的非常具体的案例:

假设我有以下类(class):

public class Student extends BaseModel{
    private int id;
    private String name;
    private Student goodFriend;
    private Student bestFriend;
}

BaseModel 只是我所有模型类的基类。

当我只是做

gson.toJson(student /* Some Student instance */);

我会得到例如:

{
 id: 1, 
 name: "Jack", 
 goodFriend: {id: 2, name: "Matt"}, 
 bestFriend: {id: 3, name "Tom"}
}

很好,但我需要的是:

{
 id: 1, 
 name: "Jack", 
 goodFriend: 2, // only an ID for this field
 bestFriend: {id: 3, name "Tom"} // whole object for this field
 // both fields are of the same Type, so I can't use TypeAdapterFactory for this
}

我需要一些方法来标记具有序列化类型(id 或对象)的字段,然后使用该标记根据需要进行序列化。我如何在 general 中做到这一点,不仅针对 Student 类,而且针对 BaseModel 的所有子类?

我唯一的想法是使用自定义注释: 描述我只想用一个注解序列化为 ID 的字段,以及我想用另一个注解序列化为对象的字段, 但我找不到在 TypeAdapter 的 write 方法中检索注释的方法。

任何想法如何处理这个?

最佳答案

我自己找到了答案。事实证明,在 GSON 中已经有针对这种情况的注释。它叫做@JsonAdapter。

首先我必须创建一个 TypeAdapterFactory:

public class BaseModelForeignKeyTypeAdapterFactory implements TypeAdapterFactory {

    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        if (!BaseModel.class.isAssignableFrom(type.getRawType())) {
            return null;
        }

        TypeAdapter defaultAdapter = gson.getAdapter(type);

        //noinspection unchecked
        return (TypeAdapter<T>) new Adapter(defaultAdapter);
    }

    private static class Adapter<T extends BaseModel> extends TypeAdapter<T> {

        private final TypeAdapter<T> defaultAdapter;

        Adapter(TypeAdapter<T> defaultAdapter) {
            this.defaultAdapter = defaultAdapter;
        }

        @Override
        public void write(JsonWriter out, T value) throws IOException {
            out.value(value.getId());
        }

        @Override
        public T read(JsonReader in) throws IOException {
            return defaultAdapter.read(in);
        }
    }
}

create() 方法中,我检索 Gson 将用于此字段的默认适配器,并将其传递给适配器以在反序列化字段时使用。这样这个适配器只用于序列化,而反序列化委托(delegate)给默认适配器。

现在我只需要注释我的 Student 类中的字段,我想使用此 TypeAdapterFactory 将其序列化为 ID,如下所示:

public class Student extends BaseModel{
    private int id;
    private String name;

    @JsonAdapter(BaseModelForeignKeyTypeAdapterFactory.class)
    private Student goodFriend;

    private Student bestFriend;
}

这就是全部,现在 gson.toJson(student) 将输出:

{
 id: 1, 
 name: "Jack", 
 goodFriend: 2, // using "ForeignKey" TypeAdapter
 bestFriend: {id: 3, name "Tom"} // using default TypeAdapter
}

我希望这对某人有帮助!

关于java - 带有注解的 GSON 自定义序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43813354/

相关文章:

java - 我不明白为什么我的 "Comparable"接口(interface)不工作

Java 博客和论坛实现

java - 如何检索联系人的电话号码(Android)?

Java - 如何检查一个类是否继承自某个类或接口(interface)?

php - 在类中查找属性的范围

java - 我怎样才能用 Guava 获得给定包的所有类

java - 使用 Kotlin 在泛型类中获取 getter(或方法或属性)列表

java - Jackson 序列化一对多关系

android - Espresso 空闲资源不起作用

android - 什么安卓手机开发应用最好