带注释的 GSON 自定义序列化 [英] GSON Custom serialization with annotations

查看:33
本文介绍了带注释的 GSON 自定义序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a very specific case of custom serialization with GSON:

假设我有以下课程:

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

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

BaseModel is just a base class for all my model classes.

当我只是做

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

我会得到例如:

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

没关系,但我需要的是:

It's fine, but what I need is this:

{
 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 的所有子类?

I need some way of marking the fields with serialization type (id or object) and then using that marking to serialize as needed. How do I do that in general, not just for a Student class, but for all subclasses of BaseModel?

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

My only idea was to use custom annotations: describing the fields that I want to serialize as ID only with one annotation, and fields that I want to serialize as objects with another annotation, but I couldn't find a way to retrieve the annotations in TypeAdapter's write method.

任何想法如何处理这个?

Any ideas how to handle this?

推荐答案

我自己找到了答案.事实证明,GSON 中已经有这种情况的注释.它被称为@JsonAdapter.

I found an answer myself. It turns out there already is an annotation for this kind of case in GSON. It's called @JsonAdapter.

首先我必须创建一个 TypeAdapterFactory:

First I had to create a 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 将用于此字段的默认适配器,并将其传递给适配器以在反序列化该字段时使用.这样这个Adapter只用于序列化,反序列化则委托给默认的Adapter.

In the create() method I retrieve the default adapter Gson would use for this field and pass it to the Adapter for use when deserializing the field. This way this Adapter is only used for serialization, while deserialization is delegated to the default adapter.

现在我只需要注释我的 Student 类中的字段,我想像这样使用 TypeAdapterFactory 将其序列化为 ID:

Now I just need to annotate the fields in my Student class, which I want to be serialized as IDs with this TypeAdapterFactory like this:

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

    @JsonAdapter(BaseModelForeignKeyTypeAdapterFactory.class)
    private Student goodFriend;

    private Student bestFriend;
}

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

And this is all, now gson.toJson(student) will output:

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

我希望这对某人有所帮助!

I hope this helps someone!

这篇关于带注释的 GSON 自定义序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆