GSON自定义序列化注释

时间:2017-05-05 20:33:09

标签: java android reflection annotations gson

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

我们说我有以下课程:

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或object)标记字段,然后根据需要使用该标记进行序列化。我如何在一般中做到这一点,不仅仅是针对Student类,而是针对BaseModel的所有子类?

我唯一的想法是使用自定义注释: 使用一个注释描述我想要序列化为ID的字段,以及将我想要序列化为具有另一个注释的对象的字段, 但是我无法找到一种方法来检索TypeAdapter写入方法中的注释。

任何想法如何处理?

1 个答案:

答案 0 :(得分:6)

我自己找到了答案。事实证明,在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将用于此字段的默认适配器,并将其传递给适配器,以便在反序列化字段时使用。这样,此适配器仅用于序列化,而反序列化则委托给默认适配器。

现在我只需要注释我的 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
}

我希望这有助于某人!

相关问题