[英]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.