java - 使用gson序列化具有泛型类型的类?
问题描述
我有以下课程
private static class ClassWithGenericType<T> {
Set<T> values;
}
如果我现在用 - 值初始化类,Set
使用Enum
gson 序列化和反序列化对象,Set
反序列化对象的 不包含Enum
- 值,但值 as String
。
我认为这是因为泛型类型通过序列化被丢弃了。我看到了,我可以使用new TypeToken<...>(){}.getType();
,但问题是,上面的类是更大对象的一部分,所以我不能gson.fromJson(classWithGenericType, typeToken)
直接调用。
有解决这个问题的聪明方法吗?我想到了 a 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
使用泛型类型序列化 a。
var gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapterFactory(new SetTypeAdapterFactory());
var gson = gsonBuilder.create();
序列化Set
后的结构如下:
[
{
"@type":<class_name_first_element>,
"@data":<first_element_as_json>
},
...
]
推荐阅读
- python - 使用静态分析和 Jedi 查找 Python 基类
- javascript - 使用 vega-embed 的 Vega-lite 重置视图
- css - CSS:文本不可见
- sql - SQL如何根据父子关系同时插入/更新/删除
- netdata - 多台服务器的网络数据显示,就像在他们的云上显示的那样。我可以在没有云的情况下做到这一点吗?
- r - 有条件地识别观察
- pine-script - 如何在 Pine Editor 中添加代码以交叉检查同一股票代码的不同时间范围的图表
- c# - 如何以非常具体的方式格式化 Serilog JSON 输出
- amazon-web-services - 无法更新 aws 传输服务器上的安全组
- vscode-debugger - 有没有办法在用 Vite 启动的 VsCode 中调试代码?