Не могу придумать лучшей формулировки для этого вопроса, но в основном я хочу сохранить имя конкретного класса в GSON (см.« движение » ):
{
"player" : {
"position" : { "x" : 300, "y" : 400 },
"scale" : 1,
"rotation" : 0,
"sprite" : {
"frames" : [ {
"fileName" : "data/plane.png"
} ],
"duration" : 1
}
},
"movementDelay" : { "elapsed" : 0, "started" : 0, "delay" : 150 },
"movement" : { "class" : "controller.TopDownGridMovement" }
}
Это класс, содержащий интерфейс Movement, который я хочу десериализовать:
public class PlayerController {
private Player player;
private DelayTimer movementDelay;
private Movement movement;
public PlayerController() {
}
[...]
}
Я написал Custom Deserializer:
package gson;
import java.lang.reflect.Type;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import controller.Movement;
public class MovementDeserialiser implements JsonDeserializer<Movement> {
@Override
public Movement deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
try {
JsonObject obj = (JsonObject) json;
Class clazz = Class.forName(obj.get("class").getAsString());
return (Movement) clazz.newInstance();
} catch (Exception e) {
throw new JsonParseException(e.getMessage());
}
}
}
Я зарегистрировал десериализатор:
public void registerAdapters(GsonBuilder gsonBuilder) {
gsonBuilder.registerTypeAdapter(Image.class, new ImageDeserialiser());
gsonBuilder.registerTypeAdapter(Button.class, new ButtonDeserialiser());
gsonBuilder.registerTypeAdapter(Animation.class, new AnimationDeserialiser());
gsonBuilder.registerTypeAdapter(Movement.class, new MovementDeserialiser());
}
Затем я попытался десериализовать класс, содержащий Movement interface:
playerController = gson.fromJson(new FileReader("data/player_data/player_data.json"), PlayerController.class);
Но я получаю эту ошибку:
ОШИБКА: невозможно вызвать конструктор без аргументов для контроллера интерфейса. Перемещение. Зарегистрируйте InstanceCreator в Gson, поскольку этот тип может решить эту проблему.
Что мне нужно сделать, чтобы это сработало? Идея указать загружаемый класс пришла из конфигурации компонента Spring - не уверен, есть ли лучший способ сделать это.
О, и из прочитанного, что я сделал, я решил, что мне не нужно создавать InstanceCreator для Movement. В конце концов, я предоставляю специальный десериализатор ...
Ура.