在GSON中反序列化接口

时间:2011-10-21 23:49:48

标签: java json class interface 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接口的类:

playerController = gson.fromJson(new FileReader("data/player_data/player_data.json"), PlayerController.class);

但是我收到了这个错误:

  

错误:无法为接口controller.Movement调用no-args构造函数。使用Gson为此类型注册InstanceCreator可以解决此问题。

我需要做些什么才能让它发挥作用?指定要加载的类的想法来自Spring的bean配置 - 不确定是否有更好的方法。

哦,从我所做的阅读中,我确定我不应该为运动创建一个InstanceCreator。毕竟我正在提供一个自定义解串器......

干杯。

2 个答案:

答案 0 :(得分:0)

验证controller.TopDownGridMovement有一个无参数构造函数。如果没有,则无法使用以下方法创建类的实例:

return (Movement) clazz.newInstance();

答案 1 :(得分:0)

啊......我以前在任何需要的地方创建了一个新的Gson实例,但最近创建了一个GsonInstance单例,我注册了我的自定义序列化器。 Move对象被反序列化的Gson对象不是GsonInstance对象,所以Gson不知道如何序列化它。愚蠢的错误。

tl; dr:我没有使用我正在使用的特定Gson实例注册自定义序列化程序。

相关问题