我正在使用GSON将通用序列化器应用于抽象Base
类的所有子类。但是,当给定Base
类的实际子类时,GSON不会调用我的序列化程序,除非明确告知要使用Base.class
作为强制类型转换。这是我在说的一个简单实例。
public interface Base<T>{
String getName();
public List<Object> getChildren();
}
public class Derived1 implements Base<Integer>{
private Integer x = 5;
String getName(){
return "Name: " + x;
}
List<Object> getChildren(){
return Lists.newArrayList(new Derived2(), "Some string");
}
}
public class Derived2 implements Base<Double>{
private Double x = 6.3;
String getName(){
return "Name: " + x;
}
List<Object> getChildren(){
return new List<>();
}
}
我正在创建如下的序列化器:
JsonSerializer customAdapter = new JsonSerializer<Base>(){
@Override
JsonElement serialize(Base base, Type sourceType, JsonSerializationContext context){
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("name", base.getName());
JsonArray jsonArray = new JsonArray();
for (Object child : base.getChildren()){
jsonArray.add(context.serialize(child));
}
if (jsonArray.size() != 0){
jsonObject.add("children", jsonArray);
}
}
};
Gson customSerializer = new GsonBuilder()
.registerTypeAdapter(Base.class, customAdapter)
.create();
但是,将我的自定义序列化程序应用于List
子类并没有达到预期的效果。
customSerializer.toJson(Lists.newArrayList(new Derived1(), new Derived2()));
这会将默认GSON序列化应用于我的子类。有什么简单的方法可以让我的自定义序列化程序在父类的所有子类上使用我的自定义适配器?我怀疑一种解决方案是使用反射对Base
的所有子类进行迭代并注册自定义适配器,但是如果可能的话,我想避免类似的事情。
注意:我现在不在乎反序列化。
答案 0 :(得分:2)
也许您不应该使用JsonSerializer
。也就是说,如果您使用TypeAdapter
通过注册TypeAdapterFactory
来告诉Gson
如何序列化任何类来做同样的事情,这是可能的。
请参见下面的TypeAdapterFactory
和TypeAdapter
:
public class CustomAdapterFactory implements TypeAdapterFactory {
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
// If the class that type token represents is a subclass of Base
// then return your special adapter
if(Base.class.isAssignableFrom(typeToken.getRawType())) {
return (TypeAdapter<T>) customTypeAdapter;
}
return null;
}
private TypeAdapter<Base<?>> customTypeAdapter = new TypeAdapter<Base<?>>() {
@Override
public void write(JsonWriter out, Base<?> value) throws IOException {
out.beginObject();
out.value(value.getName());
out.endObject();
}
@Override
public Base<?> read(JsonReader in) throws IOException {
// Deserializing to subclasses not interesting yet.
// Actually it is impossible if the JSON does not contain
// information about the subclass to which to deserialize
return null;
}
};
}
如果您执行以下操作:
@Slf4j
public class SubClassTest {
@Test
public void testIt() {
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapterFactory(new CustomAdapterFactory())
.create();
log.info("\n{}", gson.toJson(new Derived1()));
log.info("\n{}", gson.toJson(new Derived2()));
}
}
输出将如下所示:
2018-10-12 23:13:17.037信息 org.example.gson.subclass.SubClassTest:19-{“ name”:“ Name:5”} 2018-10-12 23:13:17.043信息 org.example.gson.subclass.SubClassTest:20-{“ name”:“ Name:6.3” }
如果不是您想要的,只需修复write(..)
中的customTypeAdapter
方法。