Czym jest klasa abstrakcyjna?
To Ci odpowie w czym jest problem, myślisz dobrze, jednak źle troszke to stosujesz spójrz na twoje mapowanie typu
new TypeToken<List<Shape>>() {}.getType();
wywołujesz pobranie typu dla Szape, i utworzenie obiektu z typem Shape... a klasa abstrakcyjna na to nie zezwala, skąd Java, ma wiedzieć, tzn TypeToken, że obiekty zapisywane wewnątrz są "Kołem, Kwadratem etc" ?
Równie dobrze mógłbyś mieć tam zapisane śmieci elipsy, proste ... albo zwierzęta, próbująć to ubrać w opakowanie "Shape"
Aby deserializować takie obiekty, możesz albo korzystać z Object Mappera on ma lepszy zestaw metod do tego
Druga opcja to napisanie własnego mappera, spróbuj :
public class ShapeDeserialize implements JsonDeserializer<Shape> {
private String shapeTypeElementName;
private Gson gson;
private Map<String, Class<? extends Shape>>shapeTypeRegistry;
public ShapeDeserializer(String shapeTypeElementName) {
this.shapeTypeElementName = shapeTypeElementName;
this.gson = new Gson();
this.shapeTypeRegistry = new HashMap<>();
}
public void registerBarnType(String shapeTypeName, Class<? extends Shape> shapeType) {
shapeTypeRegistry.put(shapeTypeName,shapeType);
}
public Shape deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
JsonObject shapeObject = json.getAsJsonObject();
JsonElement shapeTypeElement = shapeObject.get(shapeTypeElementName);
Class<? extends Shape> shapeType= shapeTypeRegistry.get(shapeTypeElement.getAsString());
return gson.fromJson(shapeObject, shapeType);
}
}
i jego wykorzystanie, a ostatnia opcja to zapoznanie się z jsonem- i jego adnotacjami w zakresie Inheritance
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "_type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Kwadrat.class, name = "_type"),
@JsonSubTypes.Type(value = Trojkat.class, name = "_type"),
})
gdzie określasz jakie typy dziedziczą, rozszerzają twój kształt