[英]Serialize class with generic type using gson?
我有以下課程
private static class ClassWithGenericType<T> {
Set<T> values;
}
如果我現在用一Set
Enum
初始化類,使用 gson 序列化和反序列化對象,則反序列化對象的Set
不包含Enum
值,但值為String
。
我認為這是因為通過序列化丟棄了泛型類型。 我看到,我可以使用new TypeToken<...>(){}.getType();
,但問題是,上面的類是更大對象的一部分,所以我不能直接調用gson.fromJson(classWithGenericType, typeToken)
。
有沒有聰明的方法來解決這個問題? 我想到了一個TypeAdapter
,它不僅序列化Set
的值,而且序列化它的類型。
我現在找到了一個解決方案並創建了一個TypeAdapter
。
public class SetTypeAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, @NonNull TypeToken<T> type) {
if (!Set.class.isAssignableFrom(type.getRawType())) {
return null;
}
return (TypeAdapter<T>) new SetTypeAdapter(gson);
}
}
public class SetTypeAdapter extends TypeAdapter<Set<?>> {
public static final String TYPE = "@type";
public static final String DATA = "@data";
private final Gson gson;
public SetTypeAdapter(@NonNull Gson gson) {
this.gson = gson;
}
@Override
public void write(final JsonWriter out, final Set<?> set
) throws IOException {
out.beginArray();
for (Object item : set) {
out.beginObject();
out.name(TYPE).value(item.getClass().getName());
out.name(DATA).jsonValue(gson.toJson(item));
out.endObject();
}
out.endArray();
}
@Override
public Set<?> read(final JsonReader in) throws IOException {
final Set<Object> set = Sets.newHashSet();
in.beginArray();
while (in.hasNext()) {
in.beginObject();
set.add(readNextObject(in));
in.endObject();
}
in.endArray();
return set;
}
private Object readNextObject(JsonReader in) throws IOException {
try {
checkNextName(in, TYPE);
Class<?> cls = Class.forName(in.nextString());
checkNextName(in, DATA);
return gson.fromJson(in, cls);
} catch (ClassNotFoundException exception) {
throw new IOException(exception);
}
}
private void checkNextName(JsonReader in, String name) throws IOException {
if (!in.nextName().equals(name)) {
throw new IOException("Name was not: " + name);
}
}
}
我們可以將工廠添加到GsonBuilder
,然后我們可以使用泛型類型序列化Set
。
var gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapterFactory(new SetTypeAdapterFactory());
var gson = gsonBuilder.create();
序列化的Set
具有以下結構:
[
{
"@type":<class_name_first_element>,
"@data":<first_element_as_json>
},
...
]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.