jda*_*ski 6 java reflection android annotations gson
我有一个非常具体的GSON自定义序列化案例:
假设我有以下课程:
public class Student extends BaseModel{
private int id;
private String name;
private Student goodFriend;
private Student bestFriend;
}
Run Code Online (Sandbox Code Playgroud)
BaseModel只是我所有模型类的基类.
当我这么做的时候
gson.toJson(student /* Some Student instance */);
Run Code Online (Sandbox Code Playgroud)
我会举个例子:
{
id: 1,
name: "Jack",
goodFriend: {id: 2, name: "Matt"},
bestFriend: {id: 3, name "Tom"}
}
Run Code Online (Sandbox Code Playgroud)
这很好,但我需要的是:
{
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
}
Run Code Online (Sandbox Code Playgroud)
我需要一些方法用序列化类型(id或object)标记字段,然后根据需要使用该标记进行序列化.我一般如何做到这一点,不仅仅是针对Student类,而是针对BaseModel的所有子类?
我唯一的想法是使用自定义注释:将我想要序列化的字段描述为只有一个注释的ID,以及我希望序列化为具有另一个注释的对象的字段,但我找不到一种方法来检索注释TypeAdapter的写方法.
任何想法如何处理这个?
我自己找到了答案.事实证明,在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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
在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;
}
Run Code Online (Sandbox Code Playgroud)
这就是全部,现在gson.toJson(student)将输出:
{
id: 1,
name: "Jack",
goodFriend: 2, // using "ForeignKey" TypeAdapter
bestFriend: {id: 3, name "Tom"} // using default TypeAdapter
}
Run Code Online (Sandbox Code Playgroud)
我希望这可以帮助别人!
| 归档时间: |
|
| 查看次数: |
2810 次 |
| 最近记录: |