在 GSON 中反序列化接口

发布于 2024-12-11 10:25:10 字数 2444 浏览 0 评论 0原文

对于这个问题想不出更好的措辞,但基本上我想在 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" }
}

这是包含我想要反序列化的运动接口的类:

public class PlayerController {
    private Player player;
    private DelayTimer movementDelay;
    private Movement movement;

    public PlayerController() {
    }

    [...]
}

我写了一个自定义反序列化器:

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());
}

然后我尝试反序列化包含运动接口的类:

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

但我收到此错误:

错误:无法调用接口控制器的无参数构造函数。Movement。向 Gson 注册此类型的 InstanceCreator 可能会解决此问题。

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

哦,根据我所做的阅读,我确定我不必为运动创建 InstanceCreator。毕竟,我提供了一个自定义解串器......

干杯。

Couldn't think of better phrasing for this question, but basically I want to store the name of a concrete class in GSON (see "movement"):

{ 
    "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" }
}

This is the class that contains the Movement interface I want to deserialize:

public class PlayerController {
    private Player player;
    private DelayTimer movementDelay;
    private Movement movement;

    public PlayerController() {
    }

    [...]
}

I wrote a 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());
        }
    }

}

I registered the deserializer:

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());
}

Then I tried to deserialize the class that contains the Movement interface:

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

But I get this error:

ERROR:Unable to invoke no-args constructor for interface controller.Movement. Register an InstanceCreator with Gson for this type may fix this problem.

What do I need to do to get this to work? The idea of specifying a class to load came from Spring's bean config stuff - not sure if there's a better way to do it.

Oh, and from the reading around that I did, I determined that I shouldn't have to create an InstanceCreator for Movement. I'm providing a custom deserializer, after all...

Cheers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

停顿的约定 2024-12-18 10:25:10

验证 controller.TopDownGridMovement 是否有无参数构造函数。如果没有,那么您无法使用以下命令创建该类的实例:

return (Movement) clazz.newInstance();

Verify controller.TopDownGridMovement has a no-arg constructor. If it does not then you cannot create an instance of the class using:

return (Movement) clazz.newInstance();
獨角戲 2024-12-18 10:25:10

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

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

Ah... I had previously been creating a new Gson instance wherever I needed one, but recently created a GsonInstance singleton that I registered my custom serializers with. The Gson object that the Movement object was being deserialized from was not the GsonInstance object, so Gson didn't know how to serialize it I guess. Silly mistake.

tl;dr: I hadn't registered the custom serializer with the particular Gson instance I was using.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文