Десериализация интерфейса в GSON

Не могу придумать лучшей формулировки для этого вопроса, но в основном я хочу сохранить имя конкретного класса в 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. В конце концов, я предоставляю специальный десериализатор ...

Ура.

6
задан Mitch 21 October 2011 в 23:55
поделиться